Class: GraphQL::Metrics::Analyzer

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query_or_multiplex) ⇒ Analyzer

Returns a new instance of Analyzer.



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

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)


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

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

#extract_fields_with_runtime_metricsObject



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/graphql/metrics/analyzer.rb', line 57

def extract_fields_with_runtime_metrics
  return if query.context[SKIP_FIELD_AND_ARGUMENT_METRICS]

  ns = query.context.namespace(CONTEXT_NAMESPACE)

  @static_field_metrics.each do |static_metrics|
    resolver_timings = ns[GraphQL::Metrics::INLINE_FIELD_TIMINGS][static_metrics[:path]]
    lazy_field_timings = ns[GraphQL::Metrics::LAZY_FIELD_TIMINGS][static_metrics[:path]]

    metrics = static_metrics.merge(
      resolver_timings: resolver_timings || [],
      lazy_resolver_timings: lazy_field_timings || [],
    )

    field_extracted(metrics)
  end
end

#extract_query(runtime_query_metrics: {}) ⇒ Object



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

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

#on_enter_operation_definition(_node, _parent, visitor) ⇒ Object



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

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



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

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

  # NOTE: @rmosolgo "I think it could be reduced to `arguments = visitor.arguments_for(ast_node)`"
  arguments = visitor.arguments_for(node, visitor.field_definition)
  extract_arguments(arguments.argument_values.values, visitor.field_definition)

  static_metrics = {
    field_name: node.name,
    return_type_name: visitor.type_definition.name,
    parent_type_name: visitor.parent_type_definition.name,
    deprecated: visitor.field_definition.deprecation_reason.present?,
    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



75
76
77
78
79
80
81
82
83
84
# File 'lib/graphql/metrics/analyzer.rb', line 75

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