Class PhusionPassenger::AnalyticsLogger
In: lib/phusion_passenger/analytics_logger.rb
Parent: Object

Methods

Included Modules

Utils

Classes and Modules

Class PhusionPassenger::AnalyticsLogger::Lock
Class PhusionPassenger::AnalyticsLogger::Log
Class PhusionPassenger::AnalyticsLogger::SharedData

Constants

RETRY_SLEEP = 0.2
NETWORK_ERRORS = [Errno::EPIPE, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EHOSTUNREACH, Errno::ENETDOWN, Errno::ENETUNREACH, Errno::ETIMEDOUT]
RANDOM_CHARS = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

Attributes

max_connect_tries  [RW] 
reconnect_timeout  [RW] 

Public Class methods

[Source]

     # File lib/phusion_passenger/analytics_logger.rb, line 161
161:         def initialize(logging_agent_address, username, password, node_name)
162:                 @server_address = logging_agent_address
163:                 @username = username
164:                 @password = password
165:                 if node_name && !node_name.empty?
166:                         @node_name = node_name
167:                 else
168:                         @node_name = `hostname`.strip
169:                 end
170:                 @random_dev = File.open("/dev/urandom")
171:                 
172:                 # This mutex protects the following instance variables, but
173:                 # not the contents of @shared_data.
174:                 @mutex = Mutex.new
175:                 
176:                 @shared_data = SharedData.new
177:                 if @server_address && local_socket_address?(@server_address)
178:                         @max_connect_tries = 10
179:                 else
180:                         @max_connect_tries = 1
181:                 end
182:                 @reconnect_timeout = 1
183:                 @next_reconnect_time = Time.utc(1980, 1, 1)
184:         end

[Source]

     # File lib/phusion_passenger/analytics_logger.rb, line 147
147:         def self.new_from_options(options)
148:                 if options["analytics"] && options["logging_agent_address"]
149:                         return new(options["logging_agent_address"],
150:                                 options["logging_agent_username"],
151:                                 options["logging_agent_password_base64"].unpack('m').first,
152:                                 options["node_name"])
153:                 else
154:                         return nil
155:                 end
156:         end

Public Instance methods

[Source]

     # File lib/phusion_passenger/analytics_logger.rb, line 186
186:         def clear_connection
187:                 @mutex.synchronize do
188:                         @shared_data.synchronize do
189:                                 @random_dev = File.open("/dev/urandom") if @random_dev.closed?
190:                                 @shared_data.unref
191:                                 @shared_data = SharedData.new
192:                         end
193:                 end
194:         end

[Source]

     # File lib/phusion_passenger/analytics_logger.rb, line 196
196:         def close
197:                 @mutex.synchronize do
198:                         @shared_data.synchronize do
199:                                 @random_dev.close
200:                                 @shared_data.unref
201:                                 @shared_data = nil
202:                         end
203:                 end
204:         end

[Source]

     # File lib/phusion_passenger/analytics_logger.rb, line 256
256:         def continue_transaction(txn_id, group_name, category = :requests, union_station_key = nil)
257:                 if !@server_address
258:                         return Log.new
259:                 elsif !txn_id || txn_id.empty?
260:                         raise ArgumentError, "Transaction ID may not be empty"
261:                 end
262:                 
263:                 Lock.new(@mutex).synchronize do |lock|
264:                 Lock.new(@shared_data.mutex).synchronize do |shared_data_lock|
265:                         try_count = 0
266:                         if current_time >= @next_reconnect_time
267:                                 while try_count < @max_connect_tries
268:                                         begin
269:                                                 connect if !connected?
270:                                                 @shared_data.client.write("openTransaction",
271:                                                         txn_id, group_name, "", category,
272:                                                         AnalyticsLogger.timestamp_string,
273:                                                         union_station_key,
274:                                                         true)
275:                                                 return Log.new(@shared_data, txn_id)
276:                                         rescue Errno::ENOENT, *NETWORK_ERRORS
277:                                                 try_count += 1
278:                                                 disconnect(true)
279:                                                 shared_data_lock.reset(@shared_data.mutex, false)
280:                                                 lock.unlock
281:                                                 sleep RETRY_SLEEP if try_count < @max_connect_tries
282:                                                 lock.lock
283:                                                 shared_data_lock.lock
284:                                         rescue Exception => e
285:                                                 disconnect
286:                                                 raise e
287:                                         end
288:                                 end
289:                                 # Failed to connect.
290:                                 DebugLogging.warn("Cannot connect to the logging agent (#{@server_address}); " +
291:                                         "retrying in #{@reconnect_timeout} second(s).")
292:                                 @next_reconnect_time = current_time + @reconnect_timeout
293:                         end
294:                         return Log.new
295:                 end
296:                 end
297:         end

[Source]

     # File lib/phusion_passenger/analytics_logger.rb, line 206
206:         def new_transaction(group_name, category = :requests, union_station_key = nil)
207:                 if !@server_address
208:                         return Log.new
209:                 elsif !group_name || group_name.empty?
210:                         raise ArgumentError, "Group name may not be empty"
211:                 end
212:                 
213:                 txn_id = (AnalyticsLogger.current_time.to_i / 60).to_s(36)
214:                 txn_id << "-#{random_token(11)}"
215:                 Lock.new(@mutex).synchronize do |lock|
216:                 Lock.new(@shared_data.mutex).synchronize do |shared_data_lock|
217:                         try_count = 0
218:                         if current_time >= @next_reconnect_time
219:                                 while try_count < @max_connect_tries
220:                                         begin
221:                                                 connect if !connected?
222:                                                 @shared_data.client.write("openTransaction",
223:                                                         txn_id, group_name, "", category,
224:                                                         AnalyticsLogger.timestamp_string,
225:                                                         union_station_key,
226:                                                         true,
227:                                                         true)
228:                                                 result = @shared_data.client.read
229:                                                 if result != ["ok"]
230:                                                         raise "Expected logging server to respond with 'ok', but got #{result.inspect} instead"
231:                                                 end
232:                                                 return Log.new(@shared_data, txn_id)
233:                                         rescue Errno::ENOENT, *NETWORK_ERRORS
234:                                                 try_count += 1
235:                                                 disconnect(true)
236:                                                 shared_data_lock.reset(@shared_data.mutex, false)
237:                                                 lock.unlock
238:                                                 sleep RETRY_SLEEP if try_count < @max_connect_tries
239:                                                 lock.lock
240:                                                 shared_data_lock.lock
241:                                         rescue Exception => e
242:                                                 disconnect
243:                                                 raise e
244:                                         end
245:                                 end
246:                                 # Failed to connect.
247:                                 DebugLogging.warn("Cannot connect to the logging agent (#{@server_address}); " +
248:                                         "retrying in #{@reconnect_timeout} second(s).")
249:                                 @next_reconnect_time = current_time + @reconnect_timeout
250:                         end
251:                         return Log.new
252:                 end
253:                 end
254:         end

[Validate]