Class: OpticsAgent::Agent

Inherits:
Object
  • Object
show all
Includes:
Reporting
Defined in:
lib/optics-agent/agent.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Reporting

#add_latency, #client_info, #duration_micros, #duration_nanos, #generate_report_header, #generate_timestamp, #latency_bucket_for_duration

Constructor Details

#initializeAgent

Returns a new instance of Agent.



15
16
17
18
19
20
21
# File 'lib/optics-agent/agent.rb', line 15

def initialize
  @query_queue = []
  @semaphone = Mutex.new

  # set defaults
  @configuration = Configuration.new
end

Instance Attribute Details

#report_tracesObject (readonly)

Returns the value of attribute report_traces.



13
14
15
# File 'lib/optics-agent/agent.rb', line 13

def report_traces
  @report_traces
end

#schemaObject (readonly)

Returns the value of attribute schema.



13
14
15
# File 'lib/optics-agent/agent.rb', line 13

def schema
  @schema
end

Instance Method Details

#add_query(*args) ⇒ Object



106
107
108
109
110
111
# File 'lib/optics-agent/agent.rb', line 106

def add_query(*args)
  @semaphone.synchronize {
    debug { "adding query to queue, queue length was #{@query_queue.length}" }
    @query_queue << args
  }
end

#clear_query_queueObject



113
114
115
116
117
118
119
120
# File 'lib/optics-agent/agent.rb', line 113

def clear_query_queue
  @semaphone.synchronize {
    debug { "clearing query queue, queue length was #{@query_queue.length}" }
    queue = @query_queue
    @query_queue = []
    queue
  }
end

#configure(&block) ⇒ Object



23
24
25
26
27
28
29
# File 'lib/optics-agent/agent.rb', line 23

def configure(&block)
  @configuration.instance_eval(&block)

  if @configuration.schema && @schema != @configuration.schema
    instrument_schema(@configuration.schema)
  end
end

#debug(message = nil) ⇒ Object



160
161
162
163
164
165
# File 'lib/optics-agent/agent.rb', line 160

def debug(message = nil)
  if @configuration.debug
    message = yield unless message
    log "DEBUG: #{message} <#{Process.pid} | #{Thread.current.object_id}>"
  end
end

#disabled?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/optics-agent/agent.rb', line 31

def disabled?
  @configuration.disable_reporting || !@configuration.api_key || !@schema
end

#ensure_reporting!Object

We call this method on every request to ensure that the reporting thread is active in the correct process for pre-forking webservers like unicorn



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/optics-agent/agent.rb', line 71

def ensure_reporting!
  unless @schema
    warn """No schema instrumented.
Use the `schema` configuration setting, or call `agent.instrument_schema`
"""
    return
  end

  unless @reporting_thread_active || disabled?
    schedule_report
    @reporting_thread_active = true
  end
end

#graphql_middlewareObject



129
130
131
# File 'lib/optics-agent/agent.rb', line 129

def graphql_middleware
  warn "You no longer need to pass the optics agent middleware, it now attaches itself"
end

#instrument_schema(schema) ⇒ Object



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
# File 'lib/optics-agent/agent.rb', line 39

def instrument_schema(schema)
  unless @configuration.api_key
    warn """No api_key set.
Either configure it or use the OPTICS_API_KEY environment variable.
"""
    return
  end

  if @schema
    warn """Agent has already instrumented a schema.
Perhaps you are calling both `agent.configure { schema YourSchema }` and
`agent.instrument_schema YourSchema`?
"""
    return
  end

  @schema = schema
  @schema._attach_optics_agent(self)

  unless disabled?
    debug "spawning schema thread"
    Thread.new do
      debug "schema thread spawned"
      sleep @configuration.schema_report_delay_ms / 1000.0
      debug "running schema job"
      SchemaJob.new.perform(self)
    end
  end
end

#log(message = nil) ⇒ Object



151
152
153
154
# File 'lib/optics-agent/agent.rb', line 151

def log(message = nil)
  message = yield unless message
  puts "optics-agent: #{message}"
end

#rack_middlewareObject



122
123
124
125
126
127
# File 'lib/optics-agent/agent.rb', line 122

def rack_middleware
  # We need to pass ourselves to the class we return here because
  # rack will instanciate it. (See comment at the top of RackMiddleware)
  OpticsAgent::RackMiddleware.agent = self
  OpticsAgent::RackMiddleware
end

#report_traces?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/optics-agent/agent.rb', line 35

def report_traces?
  @configuration.report_traces
end

#reporting_connectionObject



85
86
87
88
89
90
91
# File 'lib/optics-agent/agent.rb', line 85

def reporting_connection
  @reporting_connection ||=
    Faraday.new(:url => @configuration.endpoint_url) do |faraday|
      # XXX: allow setting adaptor in config
      faraday.adapter :net_http_persistent
    end
end

#schedule_reportObject



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/optics-agent/agent.rb', line 93

def schedule_report
  debug "spawning reporting thread"
  Thread.new do
    debug "reporting thread spawned"
    while true
      sleep @configuration.report_interval_ms / 1000.0
      debug "running reporting job"
      ReportJob.new.perform(self)
      debug "finished running reporting job"
    end
  end
end

#send_message(path, message) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/optics-agent/agent.rb', line 133

def send_message(path, message)
  response = reporting_connection.post do |request|
    request.url path
    request.headers['x-api-key'] = @configuration.api_key
    request.headers['user-agent'] = "optics-agent-rb"

    request.body = message.class.encode(message)
    if @configuration.debug || @configuration.print_reports
      log "sending message: #{message.class.encode_json(message)}"
    end
  end

  if @configuration.debug || @configuration.print_reports
    log "got response: #{response}"
    log "response body: #{response.body}"
  end
end

#warn(message = nil) ⇒ Object



156
157
158
# File 'lib/optics-agent/agent.rb', line 156

def warn(message = nil)
  log "WARNING: #{message}"
end