Class: ApolloStudioTracing::TraceChannel

Inherits:
Object
  • Object
show all
Defined in:
lib/apollo-studio-tracing/trace_channel.rb

Overview

rubocop:disable Metrics/ClassLength

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(report_header:, compress: nil, api_key: nil, reporting_interval: nil, max_uncompressed_report_size: nil, max_queue_bytes: nil, debug_reports: nil, max_upload_attempts: nil, min_upload_retry_delay_secs: nil) ⇒ TraceChannel

rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 22

def initialize(report_header:, compress: nil, api_key: nil, reporting_interval: nil,
               max_uncompressed_report_size: nil, max_queue_bytes: nil, debug_reports: nil,
               max_upload_attempts: nil, min_upload_retry_delay_secs: nil)
  @report_header = report_header
  @compress = compress.nil? ? true : compress
  @api_key = api_key || ENV.fetch('ENGINE_API_KEY', ENV.fetch('APOLLO_KEY', 'NO_API_KEY'))
  @reporting_interval = reporting_interval || 5
  @max_uncompressed_report_size = max_uncompressed_report_size || 4 * 1024 * 1024
  @max_queue_bytes = max_queue_bytes || @max_uncompressed_report_size * 10
  @max_upload_attempts = max_upload_attempts || 5
  @min_upload_retry_delay_secs = min_upload_retry_delay_secs || 0.1
  @debug_reports = debug_reports.nil? ? false : debug_reports
  @queue = Queue.new
  @queue_bytes = Concurrent::AtomicFixnum.new(0)
  @queue_full = false
  @enqueue_mutex = Mutex.new
  @shutdown_barrier = ApolloStudioTracing::ShutdownBarrier.new
end

Instance Attribute Details

#api_keyObject (readonly)

Returns the value of attribute api_key.



10
11
12
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 10

def api_key
  @api_key
end

#compressObject (readonly)

Returns the value of attribute compress.



10
11
12
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 10

def compress
  @compress
end

#debug_reportsObject (readonly) Also known as: debug_reports?

Returns the value of attribute debug_reports.



10
11
12
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 10

def debug_reports
  @debug_reports
end

#max_queue_bytesObject (readonly)

Returns the value of attribute max_queue_bytes.



10
11
12
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 10

def max_queue_bytes
  @max_queue_bytes
end

#max_uncompressed_report_sizeObject (readonly)

Returns the value of attribute max_uncompressed_report_size.



10
11
12
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 10

def max_uncompressed_report_size
  @max_uncompressed_report_size
end

#max_upload_attemptsObject (readonly)

Returns the value of attribute max_upload_attempts.



10
11
12
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 10

def max_upload_attempts
  @max_upload_attempts
end

#min_upload_retry_delay_secsObject (readonly)

Returns the value of attribute min_upload_retry_delay_secs.



10
11
12
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 10

def min_upload_retry_delay_secs
  @min_upload_retry_delay_secs
end

#reporting_intervalObject (readonly)

Returns the value of attribute reporting_interval.



10
11
12
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 10

def reporting_interval
  @reporting_interval
end

Instance Method Details

#ensure_thread_startedObject



89
90
91
92
93
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 89

def ensure_thread_started
  return if @uploader_thread&.alive?

  start
end

#flushObject



95
96
97
98
99
100
101
102
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 95

def flush
  until @queue.empty?
    # If the uploader thread isn't running then the queue will never drain
    break unless @uploader_thread&.alive?

    sleep(0.1)
  end
end

#queue(query_key, trace, context) ⇒ Object

rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity



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
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 42

def queue(query_key, trace, context)
  @enqueue_mutex.synchronize do
    if @queue_bytes.value >= max_queue_bytes
      unless @queue_full
        ApolloStudioTracing.logger.warn(
          "Apollo tracing queue is above the threshold of #{max_queue_bytes} bytes and " \
          'trace collection will be paused.',
        )
        @queue_full = true
      end
    else
      if @queue_full
        ApolloStudioTracing.logger.info(
          "Apollo tracing queue is below the threshold of #{max_queue_bytes} bytes and " \
          'trace collection will resume.',
        )
        @queue_full = false
      end

      if debug_reports?
        ApolloStudioTracing.logger.info("Queueing a trace for #{query_key}")
      end

      proto = ApolloStudioTracing::Trace.new(
        start_time: to_proto_timestamp(trace[:start_time]),
        end_time: to_proto_timestamp(trace[:end_time]),
        duration_ns: trace[:end_time_nanos] - trace[:start_time_nanos],
        root: trace[:node_map].root,
        client_name: context[:apollo_client_name],
        client_version: context[:apollo_client_version],
      )

      encoded_trace = ApolloStudioTracing::Trace.encode(proto)
      @queue << [query_key, encoded_trace]
      @queue_bytes.increment(encoded_trace.bytesize + query_key.bytesize)

      ensure_thread_started
    end
  end
end

#shutdownObject



104
105
106
107
108
109
110
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 104

def shutdown
  return unless @uploader_thread

  ApolloStudioTracing.logger.info('Shutting down Apollo trace channel...')
  @shutdown_barrier.shutdown
  @uploader_thread.join
end

#startObject



83
84
85
86
87
# File 'lib/apollo-studio-tracing/trace_channel.rb', line 83

def start
  @uploader_thread = Thread.new do
    run_uploader
  end
end