Class: OpticsAgent::Agent
- Inherits:
-
Object
- Object
- OpticsAgent::Agent
show all
- Includes:
- Reporting
- Defined in:
- lib/optics-agent/agent.rb
Class Attribute Summary collapse
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
#initialize ⇒ Agent
Returns a new instance of Agent.
24
25
26
27
28
29
30
31
|
# File 'lib/optics-agent/agent.rb', line 24
def initialize
@stats_reporting_thread = nil
@query_queue = []
@semaphone = Mutex.new
@configuration = Configuration.new
end
|
Class Attribute Details
.logger ⇒ Object
Returns the value of attribute logger.
17
18
19
|
# File 'lib/optics-agent/agent.rb', line 17
def logger
@logger
end
|
Instance Attribute Details
#report_traces ⇒ Object
Returns the value of attribute report_traces.
22
23
24
|
# File 'lib/optics-agent/agent.rb', line 22
def report_traces
@report_traces
end
|
#schema ⇒ Object
Returns the value of attribute schema.
22
23
24
|
# File 'lib/optics-agent/agent.rb', line 22
def schema
@schema
end
|
Instance Method Details
#add_query(*args) ⇒ Object
166
167
168
169
170
171
|
# File 'lib/optics-agent/agent.rb', line 166
def add_query(*args)
@semaphone.synchronize {
debug { "adding query to queue, queue length was #{@query_queue.length}" }
@query_queue << args
}
end
|
#clear_query_queue ⇒ Object
173
174
175
176
177
178
179
180
|
# File 'lib/optics-agent/agent.rb', line 173
def clear_query_queue
@semaphone.synchronize {
debug { "clearing query queue, queue length was #{@query_queue.length}" }
queue = @query_queue
@query_queue = []
queue
}
end
|
33
34
35
36
37
38
39
|
# File 'lib/optics-agent/agent.rb', line 33
def configure(&block)
@configuration.instance_eval(&block)
if @configuration.schema && @schema != @configuration.schema
instrument_schema(@configuration.schema)
end
end
|
#debug(message = nil) ⇒ Object
Should we be using built in debug levels rather than our own “debug” flag?
220
221
222
223
224
225
|
# File 'lib/optics-agent/agent.rb', line 220
def debug(message = nil)
if @configuration.debug
message = yield unless message
self.class.logger.info "optics-agent: DEBUG: #{message} <#{Process.pid} | #{Thread.current.object_id}>"
end
end
|
#disabled? ⇒ Boolean
41
42
43
|
# File 'lib/optics-agent/agent.rb', line 41
def disabled?
@configuration.disable_reporting || !@configuration.api_key || !@schema
end
|
#ensure_reporting! ⇒ Object
Deprecated.
Use ensure_reporting_stats! instead
95
96
97
|
# File 'lib/optics-agent/agent.rb', line 95
def ensure_reporting!
ensure_reporting_stats!
end
|
#ensure_reporting_stats! ⇒ 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
81
82
83
84
85
86
87
88
89
90
91
92
|
# File 'lib/optics-agent/agent.rb', line 81
def ensure_reporting_stats!
unless @schema
warn """No schema instrumented.
Use the `schema` configuration setting, or call `agent.instrument_schema`
"""
return
end
unless reporting_stats? || disabled?
schedule_report
end
end
|
#graphql_middleware ⇒ Object
189
190
191
|
# File 'lib/optics-agent/agent.rb', line 189
def graphql_middleware
warn "You no longer need to pass the optics agent middleware, it now attaches itself"
end
|
#instrument_schema(schema) ⇒ Object
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
|
# File 'lib/optics-agent/agent.rb', line 49
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
210
211
212
213
|
# File 'lib/optics-agent/agent.rb', line 210
def log(message = nil)
message = yield unless message
self.class.logger.info "optics-agent: #{message}"
end
|
#rack_middleware ⇒ Object
182
183
184
185
186
187
|
# File 'lib/optics-agent/agent.rb', line 182
def rack_middleware
OpticsAgent::RackMiddleware.agent = self
OpticsAgent::RackMiddleware
end
|
#report_traces? ⇒ Boolean
45
46
47
|
# File 'lib/optics-agent/agent.rb', line 45
def report_traces?
@configuration.report_traces
end
|
#reporting_connection ⇒ Object
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/optics-agent/agent.rb', line 99
def reporting_connection
@reporting_connection ||=
Faraday.new(:url => @configuration.endpoint_url) do |conn|
conn.request :retry,
:max => 5,
:interval => 0.1,
:max_interval => 10,
:backoff_factor => 2,
:exceptions => [Exception],
:retry_if => ->(env, exc) { true }
conn.use OpticsAgent::Reporting::DetectServerSideError
conn.adapter :net_http_persistent
end
end
|
#reporting_stats? ⇒ Boolean
116
117
118
|
# File 'lib/optics-agent/agent.rb', line 116
def reporting_stats?
@stats_reporting_thread != nil && !!@stats_reporting_thread.status
end
|
#schedule_report ⇒ Object
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
# File 'lib/optics-agent/agent.rb', line 120
def schedule_report
@semaphone.synchronize do
return if reporting_stats?
debug "spawning reporting thread"
thread = Thread.new do
begin
debug "reporting thread spawned"
report_interval = @configuration.report_interval_ms / 1000.0
last_started = Time.now
while true
next_send = last_started + report_interval
sleep_time = next_send - Time.now
if sleep_time < 0
warn 'Report took more than one interval! Some requests might appear at the wrong time.'
else
sleep sleep_time
end
debug "running reporting job"
last_started = Time.now
ReportJob.new.perform(self)
debug "finished running reporting job"
end
rescue Exception => e
warn "Stats report thread dying: #{e}"
end
end
at_exit do
if thread.status
debug 'sending last stats report before exiting'
thread.exit
ReportJob.new.perform(self)
debug 'last stats report sent'
end
end
@stats_reporting_thread = thread
end
end
|
#send_message(path, message) ⇒ Object
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
# File 'lib/optics-agent/agent.rb', line 193
def send_message(path, message)
response = reporting_connection.post do |request|
request.url path
request.['x-api-key'] = @configuration.api_key
request.['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 body: #{response.body}"
end
end
|
#warn(message = nil) ⇒ Object
215
216
217
|
# File 'lib/optics-agent/agent.rb', line 215
def warn(message = nil)
self.class.logger.warn "optics-agent: WARNING: #{message}"
end
|