File: platform_trace.rb

package info (click to toggle)
ruby-graphql 2.2.17-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,584 kB
  • sloc: ruby: 67,505; ansic: 1,753; yacc: 831; javascript: 331; makefile: 6
file content (123 lines) | stat: -rw-r--r-- 4,212 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# frozen_string_literal: true

module GraphQL
  module Tracing
    module PlatformTrace
      def initialize(trace_scalars: false, **_options)
        @trace_scalars = trace_scalars

        @platform_key_cache = Hash.new { |h, mod| h[mod] = mod::KeyCache.new }
        super
      end

      module BaseKeyCache
        def initialize
          @platform_field_key_cache = Hash.new { |h, k| h[k] = platform_field_key(k) }
          @platform_authorized_key_cache = Hash.new { |h, k| h[k] = platform_authorized_key(k) }
          @platform_resolve_type_key_cache = Hash.new { |h, k| h[k] = platform_resolve_type_key(k) }
        end

        attr_reader :platform_field_key_cache, :platform_authorized_key_cache, :platform_resolve_type_key_cache
      end


      def platform_execute_field_lazy(*args, &block)
        platform_execute_field(*args, &block)
      end

      def platform_authorized_lazy(key, &block)
        platform_authorized(key, &block)
      end

      def platform_resolve_type_lazy(key, &block)
        platform_resolve_type(key, &block)
      end

      def self.included(child_class)
        key_methods_class = Class.new {
          include(child_class)
          include(BaseKeyCache)
        }
        child_class.const_set(:KeyCache, key_methods_class)

        # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time

        [:execute_field, :execute_field_lazy].each do |field_trace_method|
          if !child_class.method_defined?(field_trace_method)
            child_class.module_eval <<-RUBY, __FILE__, __LINE__
              def #{field_trace_method}(query:, field:, ast_node:, arguments:, object:)
                return_type = field.type.unwrap
                trace_field = if return_type.kind.scalar? || return_type.kind.enum?
                  (field.trace.nil? && @trace_scalars) || field.trace
                else
                  true
                end
                platform_key = if trace_field
                  @platform_key_cache[#{child_class}].platform_field_key_cache[field]
                else
                  nil
                end
                if platform_key && trace_field
                  platform_#{field_trace_method}(platform_key) do
                    super
                  end
                else
                  super
                end
              end
            RUBY
          end
        end


        [:authorized, :authorized_lazy].each do |auth_trace_method|
          if !child_class.method_defined?(auth_trace_method)
            child_class.module_eval <<-RUBY, __FILE__, __LINE__
              def #{auth_trace_method}(type:, query:, object:)
                platform_key = @platform_key_cache[#{child_class}].platform_authorized_key_cache[type]
                platform_#{auth_trace_method}(platform_key) do
                  super
                end
              end
            RUBY
          end
        end

        [:resolve_type, :resolve_type_lazy].each do |rt_trace_method|
          if !child_class.method_defined?(rt_trace_method)
            child_class.module_eval <<-RUBY, __FILE__, __LINE__
              def #{rt_trace_method}(query:, type:, object:)
                platform_key = @platform_key_cache[#{child_class}].platform_resolve_type_key_cache[type]
                platform_#{rt_trace_method}(platform_key) do
                  super
                end
              end
            RUBY
          end

          # rubocop:enable Development/NoEvalCop
        end
      end

      private

      # Get the transaction name based on the operation type and name if possible, or fall back to a user provided
      # one. Useful for anonymous queries.
      def transaction_name(query)
        selected_op = query.selected_operation
        txn_name = if selected_op
          op_type = selected_op.operation_type
          op_name = selected_op.name || fallback_transaction_name(query.context) || "anonymous"
          "#{op_type}.#{op_name}"
        else
          "query.anonymous"
        end
        "GraphQL/#{txn_name}"
      end

      def fallback_transaction_name(context)
        context[:tracing_fallback_transaction_name]
      end
    end
  end
end