class MoesifRack::MoesifMiddleware
Public Class Methods
new(app, options = {})
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 16 def initialize app, options = {} @app = app if not options['application_id'] raise 'application_id required for Moesif Middleware' end @api_client = MoesifApi::MoesifAPIClient.new(options['application_id']) @api_controller = @api_client.api @api_version = options['api_version'] @identify_user = options['identify_user'] @identify_company = options['identify_company'] @get_metadata = options['get_metadata'] @identify_session = options['identify_session'] @mask_data = options['mask_data'] @skip = options['skip'] @debug = options['debug'] @app_config = AppConfig.new(@debug) @helpers = Helpers.new(@debug) @config = @app_config.get_config(@api_controller) @config_etag = nil @last_config_download_time = Time.now.utc @last_worker_run = Time.now.utc @config_dict = Hash.new @disable_transaction_id = options['disable_transaction_id'] || false @log_body = options.fetch('log_body', true) @batch_size = options['batch_size'] || 25 @batch_max_time = options['batch_max_time'] || 2 @events_queue = Queue.new @event_response_config_etag = nil start_worker() begin new_config = @app_config.get_config(@api_controller) if !new_config.nil? @config, @config_etag, @last_config_download_time = @app_config.parse_configuration(new_config) end rescue => exception @helpers.log_debug 'Error while parsing application configuration on initialization' @helpers.log_debug exception.to_s end @capture_outoing_requests = options['capture_outoing_requests'] @capture_outgoing_requests = options['capture_outgoing_requests'] if @capture_outoing_requests || @capture_outgoing_requests @helpers.log_debug 'Start Capturing outgoing requests' require_relative '../../moesif_capture_outgoing/httplog.rb' MoesifCaptureOutgoing.start_capture_outgoing(options) end end
Public Instance Methods
base64_encode_body(body)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 93 def base64_encode_body(body) return Base64.encode64(body), 'base64' end
call(env)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 158 def call env start_time = Time.now.utc.iso8601(3) @helpers.log_debug('Calling Moesif middleware') status, headers, body = @app.call env end_time = Time.now.utc.iso8601(3) process_send = lambda do req = Rack::Request.new(env) complex_copy = env.dup # Filter hash to only have keys of type string complex_copy = complex_copy.select { |k, v| k.is_a? String } req_headers = {} complex_copy.select {|k,v| k.start_with?('HTTP_', 'CONTENT_') }.each do |key, val| new_key = key.sub(/^HTTP_/, '') new_key = new_key.sub('_', '-') req_headers[new_key] = val end req_body_string = req.body.read req.body.rewind req_body_transfer_encoding = nil req_body = nil if @log_body if req_body_string && req_body_string.length != 0 req_body, req_body_transfer_encoding = parse_body(req_body_string, transform_headers(req_headers)) end end rsp_headers = headers.dup rsp_body_string = get_response_body(body); rsp_body_transfer_encoding = nil rsp_body = nil if @log_body if rsp_body_string && rsp_body_string.length != 0 rsp_body, rsp_body_transfer_encoding = parse_body(rsp_body_string, transform_headers(rsp_headers)) end end event_req = MoesifApi::EventRequestModel.new() event_req.time = start_time event_req.uri = req.url event_req.verb = req.request_method if @api_version event_req.api_version = @api_version end # Add Transaction Id to the Request Header if !@disable_transaction_id req_trans_id = req_headers["X-MOESIF_TRANSACTION_ID"] if !req_trans_id.nil? transaction_id = req_trans_id if transaction_id.strip.empty? transaction_id = SecureRandom.uuid end else transaction_id = SecureRandom.uuid end # Add Transaction Id to Request Header req_headers["X-Moesif-Transaction-Id"] = transaction_id # Filter out the old key as HTTP Headers case are not preserved if req_headers.key?("X-MOESIF_TRANSACTION_ID") req_headers = req_headers.except("X-MOESIF_TRANSACTION_ID") end end # Add Transaction Id to the Response Header if !transaction_id.nil? rsp_headers["X-Moesif-Transaction-Id"] = transaction_id end # Add Transaction Id to the Repsonse Header sent to the client if !transaction_id.nil? headers["X-Moesif-Transaction-Id"] = transaction_id end event_req.ip_address = get_client_address(req.env) event_req.headers = req_headers event_req.body = req_body event_req.transfer_encoding = req_body_transfer_encoding event_rsp = MoesifApi::EventResponseModel.new() event_rsp.time = end_time event_rsp.status = status event_rsp.headers = rsp_headers event_rsp.body = rsp_body event_rsp.transfer_encoding = rsp_body_transfer_encoding event_model = MoesifApi::EventModel.new() event_model.request = event_req event_model.response = event_rsp event_model.direction = "Incoming" if @identify_user @helpers.log_debug "calling identify user proc" event_model.user_id = @identify_user.call(env, headers, body) end if @identify_company @helpers.log_debug "calling identify company proc" event_model.company_id = @identify_company.call(env, headers, body) end if @get_metadata @helpers.log_debug "calling get_metadata proc" event_model.metadata = @get_metadata.call(env, headers, body) end if @identify_session @helpers.log_debug "calling identify session proc" event_model.session_token = @identify_session.call(env, headers, body) end if @mask_data @helpers.log_debug "calling mask_data proc" event_model = @mask_data.call(event_model) end @helpers.log_debug "sending data to moesif" @helpers.log_debug event_model.to_json # Perform the API call through the SDK function begin random_percentage = Random.rand(0.00..100.00) begin sampling_percentage = @app_config.get_sampling_percentage(event_model, @config, event_model.user_id, event_model.company_id) @helpers.log_debug "Using sample rate #{sampling_percentage}" rescue => exception @helpers.log_debug 'Error while getting sampling percentage, assuming default behavior' @helpers.log_debug exception.to_s sampling_percentage = 100 end if sampling_percentage > random_percentage event_model.weight = @app_config.calculate_weight(sampling_percentage) # Add Event to the queue @events_queue << event_model @helpers.log_debug("Event added to the queue ") if Time.now.utc > (@last_worker_run + 60) start_worker() end if !@event_response_config_etag.nil? && !@config_etag.nil? && @config_etag != @event_response_config_etag && Time.now.utc > (@last_config_download_time + 300) begin new_config = @app_config.get_config(@api_controller) if !new_config.nil? @config, @config_etag, @last_config_download_time = @app_config.parse_configuration(new_config) end rescue => exception @helpers.log_debug 'Error while updating the application configuration' @helpers.log_debug exception.to_s end end else @helpers.log_debug("Skipped Event due to sampling percentage: " + sampling_percentage.to_s + " and random percentage: " + random_percentage .to_s) end rescue => exception @helpers.log_debug "Error adding event to the queue " @helpers.log_debug exception.to_s end end should_skip = false if @skip if @skip.call(env, headers, body) should_skip = true; end end if !should_skip begin process_send.call rescue => exception @helpers.log_debug 'Error while logging event - ' @helpers.log_debug exception.to_s @helpers.log_debug exception.backtrace end else @helpers.log_debug "Skipped Event using should_skip configuration option." end [status, headers, body] end
decompress_body(body)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 85 def decompress_body(body) Zlib::GzipReader.new(StringIO.new(body)).read end
get_response_body(response)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 351 def get_response_body(response) body = response.respond_to?(:body) ? response.body : response if (body.instance_of?(Hash) || body.instance_of?(Array)) return body end body = body.inject("") { |i, a| i << a } if (body.respond_to?(:each) && body.respond_to?(:inject)) body.to_s end
parse_body(body, headers)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 103 def parse_body(body, headers) begin if (body.instance_of?(Hash) || body.instance_of?(Array)) parsed_body = body transfer_encoding = 'json' elsif start_with_json(body) parsed_body = JSON.parse(body) transfer_encoding = 'json' elsif headers.key?('content-encoding') && ((headers['content-encoding'].downcase).include? "gzip") uncompressed_string = decompress_body(body) parsed_body, transfer_encoding = base64_encode_body(uncompressed_string) else parsed_body, transfer_encoding = base64_encode_body(body) end rescue parsed_body, transfer_encoding = base64_encode_body(body) end return parsed_body, transfer_encoding end
start_with_json(body)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 81 def start_with_json(body) body.start_with?('{') || body.start_with?('[') end
start_worker()
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 123 def start_worker Thread::new do @last_worker_run = Time.now.utc loop do begin until @events_queue.empty? do batch_events = [] until batch_events.size == @batch_size || @events_queue.empty? do batch_events << @events_queue.pop end @helpers.log_debug("Sending #{batch_events.size.to_s} events to Moesif") event_api_response = @api_controller.create_events_batch(batch_events) @event_response_config_etag = event_api_response[:x_moesif_config_etag] @helpers.log_debug(event_api_response.to_s) @helpers.log_debug("Events successfully sent to Moesif") end if @events_queue.empty? @helpers.log_debug("No events to read from the queue") end sleep @batch_max_time rescue MoesifApi::APIException => e if e.response_code.between?(401, 403) puts "Unathorized accesss sending event to Moesif. Please verify your Application Id." @helpers.log_debug(e.to_s) end @helpers.log_debug("Error sending event to Moesif, with status code #{e.response_code.to_s}") rescue => e @helpers.log_debug(e.to_s) end end end end
transform_headers(headers)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 89 def transform_headers(headers) Hash[headers.map { |k, v| [k.downcase, v]}] end
update_companies_batch(company_profiles)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 77 def update_companies_batch(company_profiles) CompanyHelper.new.update_companies_batch(@api_controller, @debug, company_profiles) end
update_company(company_profile)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 73 def update_company(company_profile) CompanyHelper.new.update_company(@api_controller, @debug, company_profile) end
update_user(user_profile)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 65 def update_user(user_profile) UserHelper.new.update_user(@api_controller, @debug, user_profile) end
update_users_batch(user_profiles)
click to toggle source
# File lib/moesif_rack/moesif_middleware.rb, line 69 def update_users_batch(user_profiles) UserHelper.new.update_users_batch(@api_controller, @debug, user_profiles) end