Class: GraphQL::Metrics::Analyzer

Inherits:
Analysis::AST::Analyzer
  • Object
show all
Defined in:
lib/graphql/metrics/analyzer.rb

Constant Summary collapse

DIRECTIVE_TYPE =
"__Directive"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query_or_multiplex) ⇒ Analyzer

Returns a new instance of Analyzer.



9
10
11
12
13
14
15
16
17
18
# File 'lib/graphql/metrics/analyzer.rb', line 9

def initialize(query_or_multiplex)
  super

  @query = query_or_multiplex
  ns = query.context.namespace(CONTEXT_NAMESPACE)
  ns[ANALYZER_INSTANCE_KEY] = self

  @static_query_metrics = nil
  @static_field_metrics = []
end

Instance Attribute Details

#queryObject (readonly)

Returns the value of attribute query.



6
7
8
# File 'lib/graphql/metrics/analyzer.rb', line 6

def query
  @query
end

Instance Method Details

#analyze?Boolean

Returns:

  • (Boolean)


20
21
22
# File 'lib/graphql/metrics/analyzer.rb', line 20

def analyze?
  query.valid? && !query.context[GraphQL::Metrics::SKIP_GRAPHQL_METRICS_ANALYSIS]
end

#extract_fields(with_runtime_metrics: true) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/graphql/metrics/analyzer.rb', line 61

def extract_fields(with_runtime_metrics: true)
  return if query.context[SKIP_FIELD_AND_ARGUMENT_METRICS]

  ns = query.context.namespace(CONTEXT_NAMESPACE)

  @static_field_metrics.each do |static_metrics|

    if with_runtime_metrics
      resolver_timings = ns[GraphQL::Metrics::INLINE_FIELD_TIMINGS][static_metrics[:path]]
      lazy_resolver_timings = ns[GraphQL::Metrics::LAZY_FIELD_TIMINGS][static_metrics[:path]]

      static_metrics[:resolver_timings] = resolver_timings || []
      static_metrics[:lazy_resolver_timings] = lazy_resolver_timings || []
    end

    field_extracted(static_metrics)
  end
end

#extract_query(runtime_query_metrics: {}) ⇒ Object



24
25
26
# File 'lib/graphql/metrics/analyzer.rb', line 24

def extract_query(runtime_query_metrics: {})
  query_extracted(@static_query_metrics.merge(runtime_query_metrics)) if @static_query_metrics
end

#on_enter_directive(node, parent, visitor) ⇒ Object



80
81
82
83
84
85
86
87
88
89
# File 'lib/graphql/metrics/analyzer.rb', line 80

def on_enter_directive(node, parent, visitor)
  argument_values = arguments_for(node, visitor.directive_definition)
  extract_arguments(
    argument: argument_values,
    definition: visitor.directive_definition,
    parent: parent
  ) if argument_values

  directive_extracted({ directive_name: node.name })
end

#on_enter_operation_definition(_node, _parent, visitor) ⇒ Object



28
29
30
31
32
33
# File 'lib/graphql/metrics/analyzer.rb', line 28

def on_enter_operation_definition(_node, _parent, visitor)
  @static_query_metrics = {
    operation_type: visitor.query.selected_operation.operation_type,
    operation_name: visitor.query.selected_operation.name,
  }
end

#on_leave_field(node, parent, visitor) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/graphql/metrics/analyzer.rb', line 35

def on_leave_field(node, parent, visitor)
  return if visitor.field_definition.introspection?
  return if query.context[SKIP_FIELD_AND_ARGUMENT_METRICS]

  argument_values = arguments_for(node, visitor.field_definition)
  extract_arguments(
    argument: argument_values,
    definition: visitor.field_definition,
    parent: parent
  ) if argument_values

  static_metrics = {
    field_name: node.name,
    return_type_name: visitor.type_definition.graphql_name,
    parent_type_name: visitor.parent_type_definition.graphql_name,
    deprecated: !visitor.field_definition.deprecation_reason.nil?,
    path: visitor.response_path,
  }

  if GraphQL::Metrics.timings_capture_enabled?(query.context)
    @static_field_metrics << static_metrics
  else
    field_extracted(static_metrics)
  end
end

#resultObject



91
92
93
94
95
96
97
98
99
100
# File 'lib/graphql/metrics/analyzer.rb', line 91

def result
  return if GraphQL::Metrics.timings_capture_enabled?(query.context)
  return if query.context[GraphQL::Metrics::SKIP_GRAPHQL_METRICS_ANALYSIS]

  # NOTE: If we're running as a static analyzer (i.e. not with instrumentation and tracing), we still need to
  # flush static query metrics somewhere other than `after_query`.
  ns = query.context.namespace(CONTEXT_NAMESPACE)
  analyzer = ns[GraphQL::Metrics::ANALYZER_INSTANCE_KEY]
  analyzer.extract_query
end