| Class | PhusionPassenger::AnalyticsLogger |
| In: |
lib/phusion_passenger/analytics_logger.rb
|
| Parent: | Object |
| 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'] |
| max_connect_tries | [RW] | |
| reconnect_timeout | [RW] |
# 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
# 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
# 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
# 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
# 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
# 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