Module: GraphQL::Tracing::MonitorTrace

Defined in:
lib/graphql/tracing/monitor_trace.rb

Overview

This module is the basis for Ruby-level integration with third-party monitoring platforms. Platform-specific traces include this module and implement an adapter.

Defined Under Namespace

Classes: Monitor

Constant Summary collapse

MODULE_TEMPLATE =
"# @param set_transaction_name [Boolean] If `true`, use the GraphQL operation name as the request name on the monitoring platform\n# @param trace_scalars [Boolean] If `true`, leaf fields will be traced too (Scalars _and_ Enums)\n# @param trace_authorized [Boolean] If `false`, skip tracing `authorized?` calls\n# @param trace_resolve_type [Boolean] If `false`, skip tracing `resolve_type?` calls\ndef initialize(...)\n  setup_%{monitor}_monitor(...)\n  super\nend\n\ndef setup_%{monitor}_monitor(trace_scalars: false, trace_authorized: true, trace_resolve_type: true, set_transaction_name: false, **kwargs)\n  @trace_scalars = trace_scalars\n  @trace_authorized = trace_authorized\n  @trace_resolve_type = trace_resolve_type\n  @set_transaction_name = set_transaction_name\n  @%{monitor} = %{monitor_class}.new(trace: self, set_transaction_name: @set_transaction_name, **kwargs)\nend\n\ndef parse(query_string:)\n  @%{monitor}.instrument(:parse, query_string) do\n    super\n  end\nend\n\ndef lex(query_string:)\n  @%{monitor}.instrument(:lex, query_string) do\n    super\n  end\nend\n\ndef validate(query:, validate:)\n  @%{monitor}.instrument(:validate, query) do\n    super\n  end\nend\n\ndef begin_analyze_multiplex(multiplex, analyzers)\n  begin_%{monitor}_event(:analyze, nil)\n  super\nend\n\ndef end_analyze_multiplex(multiplex, analyzers)\n  finish_%{monitor}_event\n  super\nend\n\ndef execute_multiplex(multiplex:)\n  @%{monitor}.instrument(:execute, multiplex) do\n    super\n  end\nend\n\ndef begin_execute_field(field, object, arguments, query)\n  return_type = field.type.unwrap\n  trace_field = if return_type.kind.scalar? || return_type.kind.enum?\n    (field.trace.nil? && @trace_scalars) || field.trace\n  else\n    true\n  end\n\n  if trace_field\n    begin_%{monitor}_event(:execute_field, field)\n  end\n  super\nend\n\ndef end_execute_field(field, object, arguments, query, result)\n  finish_%{monitor}_event\n  super\nend\n\ndef dataloader_fiber_yield(source)\n  Fiber[PREVIOUS_EV_KEY] = finish_%{monitor}_event\n  super\nend\n\ndef dataloader_fiber_resume(source)\n  prev_ev = Fiber[PREVIOUS_EV_KEY]\n  if prev_ev\n    begin_%{monitor}_event(prev_ev.keyword, prev_ev.object)\n  end\n  super\nend\n\ndef begin_authorized(type, object, context)\n  @trace_authorized && begin_%{monitor}_event(:authorized, type)\n  super\nend\n\ndef end_authorized(type, object, context, result)\n  finish_%{monitor}_event\n  super\nend\n\ndef begin_resolve_type(type, value, context)\n  @trace_resolve_type && begin_%{monitor}_event(:resolve_type, type)\n  super\nend\n\ndef end_resolve_type(type, value, context, resolved_type)\n  finish_%{monitor}_event\n  super\nend\n\ndef begin_dataloader_source(source)\n  begin_%{monitor}_event(:dataloader_source, source)\n  super\nend\n\ndef end_dataloader_source(source)\n  finish_%{monitor}_event\n  super\nend\n\nCURRENT_EV_KEY = :__graphql_%{monitor}_trace_event\nPREVIOUS_EV_KEY = :__graphql_%{monitor}_trace_previous_event\n\nprivate\n\ndef begin_%{monitor}_event(keyword, object)\n  Fiber[CURRENT_EV_KEY] = @%{monitor}.start_event(keyword, object)\nend\n\ndef finish_%{monitor}_event\n  if ev = Fiber[CURRENT_EV_KEY]\n    ev.finish\n    # Use `false` to prevent grabbing an event from a parent fiber\n    Fiber[CURRENT_EV_KEY] = false\n    ev\n  end\nend\n"

Class Method Summary collapse

Class Method Details

.create_module(monitor_name) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/graphql/tracing/monitor_trace.rb', line 135

def self.create_module(monitor_name)
  if !monitor_name.match?(/[a-z]+/)
    raise ArgumentError, "monitor name must be [a-z]+, not: #{monitor_name.inspect}"
  end

  trace_module = Module.new
  code = MODULE_TEMPLATE % {
    monitor: monitor_name,
    monitor_class: monitor_name.capitalize + "Monitor",
  }
  trace_module.module_eval(code, __FILE__, __LINE__ + 5) # rubocop:disable Development/NoEvalCop This is build-time with a validated string
  trace_module
end