class GCareRubyMethodProfiler
pow.gs/mirror/discourse/blob/35d6fff69e86704081270333fbcb5248202a246a/lib/method_profiler.rb
Public Class Methods
clear()
click to toggle source
# File lib/gcarerubymethodprofiler.rb, line 257 def self.clear Thread.current[:_method_profiler] = nil end
decorateForOneArgument(klass, methods, name)
click to toggle source
# File lib/gcarerubymethodprofiler.rb, line 184 def self.decorateForOneArgument(klass, methods, name) patches = methods.map do |method_name| <<~RUBY unless defined?(#{method_name}__mp_unpatched) alias_method :#{method_name}__mp_unpatched, :#{method_name} def #{method_name}(*args, &blk) unless prof = Thread.current[:_method_profiler] puts 'test1' return #{method_name}__mp_unpatched(*args, &blk) end begin start = Process.clock_gettime(Process::CLOCK_MONOTONIC) puts 'test2' a = __method__.to_s argsdata = args.to_s puts a puts argsdata #{method_name}__mp_unpatched(*args, &blk) ensure data = (prof[:#{name}] ||= {duration: 0.0, calls: 0}) data[:duration] += Process.clock_gettime(Process::CLOCK_MONOTONIC) - start data[:calls] += 1 end end end RUBY end.join("\n") klass.class_eval patches end
decorateHttp(methods, name, iKey, gcareurl, no_recurse: false)
click to toggle source
# File lib/gcarerubymethodprofiler.rb, line 10 def self.decorateHttp(methods, name, iKey, gcareurl, no_recurse: false) patches = methods.map do |method_name| recurse_protection = "" if no_recurse recurse_protection = <<~RUBY return #{method_name}__mp_unpatched(*args, &blk) if @mp_recurse_protect_#{method_name} @mp_recurse_protect_#{method_name} = true RUBY end <<~RUBY unless defined?(#{method_name}__mp_unpatched) alias_method :#{method_name}__mp_unpatched, :#{method_name} def #{method_name}(*args, &blk) unless prof = Thread.current[:_method_profiler] requestobject = nil donottrack = false gcare_telemetry_uri = URI("#{gcareurl}") case __method__.to_s when 'request' if args[0].is_a? Net::HTTPRequest requestobject = args[0] if requestobject.path == gcare_telemetry_uri.path donottrack = true else donottrack = false end end when 'get' path = args[0] when 'get_response' uri_or_host = args[0] path = args[1] port = args[2] when 'post' path = args[0] when 'post_form' uri_or_host = args[0] when 'get2' path = args[0] when 'head2' path = args[0] when 'patch' path = args[0] when 'post2' path = args[0] end gcareid = requestobject['GCareID'] if gcareid == nil gcareid = SecureRandom.uuid requestobject['GCareID'] = gcareid end startTime = Time.now #{recurse_protection} returnvalue = #{method_name}__mp_unpatched(*args, &blk) if donottrack == false donottrack = true endTime = Time.now timestamp = startTime.utc.iso8601(0) scheme = self.use_ssl? == true ? 'https' : 'http' local_host = Socket.gethostname local_ip = Resolv.getaddress(local_host) remote_host = self.address remote_ip = Resolv.getaddress(remote_host) iKeyValue = "#{iKey}" duration = Time.at(endTime - startTime).gmtime.strftime("00.%H:%M:%S.%7N") teledata = { 'ver' => 2, 'name' => 'Gavs.ApplicationMonitoring.' + iKeyValue + '.RemoteDependency', 'time' => timestamp, 'sampleRate' => '100', 'iKey' => iKeyValue, 'tags' => { 'ai' => { 'internal.sdkVersion' => 'rb:1.0.0', 'operation.id' => nil, 'operation.name' => requestobject.method, 'gcare.id' => gcareid, 'device.roleInstance' => local_host } }, 'data' => { 'baseType' => 'RemoteDependencyData', 'baseData' => { 'ver' => 2, 'platform_version' => "#{RUBY_VERSION}", 'platform_description' => 'ruby', 'id' => nil, 'GCareID' => gcareid, 'referer' => requestobject['referer'], 'scheme' => scheme, 'remote_ip' => local_ip, 'remote_host' => local_host, 'forwarding_ip' => nil, 'client_ip' => local_ip, 'server_host' => remote_host, 'server_ip' => remote_ip, 'server_hostname' => remote_host, 'useragent' => requestobject['user-agent'], 'session_id' => nil, 'timestamp' => timestamp, 'name' => requestobject.method, 'duration' => duration, 'responseCode' => returnvalue.code, 'success' => returnvalue.message, 'url' => returnvalue.uri == nil ? scheme + ":" + "//" + self.address + ":" + self.port.to_s + requestobject.path : returnvalue.uri, 'server_port' => self.port, 'properties' => { 'httpMethod' => requestobject.method } } }, 'machine' => { 'from_ip' => 'USER', 'from_name' => 'USER', 'to_ip' => remote_ip, 'to_name' => requestobject.path } } puts teledata.to_json headers = { 'Accept' => 'application/json', 'Content-Type' => 'application/json; charset=utf-8' } request = Net::HTTP::Post.new(gcare_telemetry_uri.path, headers) request.body = teledata.to_json http = Net::HTTP.new gcare_telemetry_uri.hostname, gcare_telemetry_uri.port if gcare_telemetry_uri.scheme.downcase == 'https' http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE end p "Sending RemoteDependency telemery data to GCare (http)" response = http.request(request) if !response.kind_of? Net::HTTPSuccess end end if returnvalue.is_a?(Net::HTTPResponse) end if returnvalue.is_a?(String) end return returnvalue end #{recurse_protection} begin start = Process.clock_gettime(Process::CLOCK_MONOTONIC) puts 'test2' puts args #{method_name}__mp_unpatched(*args, &blk) ensure data = (prof[:#{name}] ||= {duration: 0.0, calls: 0}) data[:duration] += Process.clock_gettime(Process::CLOCK_MONOTONIC) - start data[:calls] += 1 #{"@mp_recurse_protect_#{method_name} = false" if no_recurse} end end end RUBY end.join("\n") Net::HTTP.class_eval patches end
decorateSql(klass, methods, name)
click to toggle source
# File lib/gcarerubymethodprofiler.rb, line 215 def self.decorateSql(klass, methods, name) patches = methods.map do |method_name| <<~RUBY unless defined?(#{method_name}__mp_unpatched) alias_method :#{method_name}__mp_unpatched, :#{method_name} def #{method_name}(*args, &blk) unless prof = Thread.current[:_method_profiler] puts 'test1' return #{method_name}__mp_unpatched(*args, &blk) end begin start = Process.clock_gettime(Process::CLOCK_MONOTONIC) puts 'test2' puts args #{method_name}__mp_unpatched(*args, &blk) ensure data = (prof[:#{name}] ||= {duration: 0.0, calls: 0}) data[:duration] += Process.clock_gettime(Process::CLOCK_MONOTONIC) - start data[:calls] += 1 end end end RUBY end.join("\n") klass.class_eval patches end
start()
click to toggle source
# File lib/gcarerubymethodprofiler.rb, line 250 def self.start Thread.current[:_method_profiler] = transfer || { __start: Process.clock_gettime(Process::CLOCK_MONOTONIC) } puts "GCare Profiling Started" end
stop()
click to toggle source
# File lib/gcarerubymethodprofiler.rb, line 261 def self.stop finish = Process.clock_gettime(Process::CLOCK_MONOTONIC) if data = Thread.current[:_method_profiler] Thread.current[:_method_profiler] = nil start = data.delete(:__start) data[:total_duration] = finish - start data end puts "GCare Profiling Stopped" end
transfer()
click to toggle source
# File lib/gcarerubymethodprofiler.rb, line 243 def self.transfer result = Thread.current[:_method_profiler] Thread.current[:_method_profiler] = nil result end
Public Instance Methods
format_request_duration(duration_seconds)
click to toggle source
# File lib/gcarerubymethodprofiler.rb, line 176 def format_request_duration(duration_seconds) if duration_seconds >= 86400 # just return 1 day when it takes more than 1 day which should not happen for requests. return "%02d.%02d:%02d:%02d.%07d" % [1, 0, 0, 0, 0] end Time.at(duration_seconds).gmtime.strftime("00.%H:%M:%S.%7N") end
send(data_to_send)
click to toggle source
# File lib/gcarerubymethodprofiler.rb, line 297 def send(data_to_send) uri = URI(@service_endpoint_uri) headers = { 'Accept' => 'application/json', 'Content-Type' => 'application/json; charset=utf-8' } #, # 'Content-Encoding' => 'gzip' # currently no encryption enabled request = Net::HTTP::Post.new(uri.path, headers) # Use JSON.generate instead of to_json, otherwise it will # default to ActiveSupport::JSON.encode for Rails app json = JSON.generate(data_to_send) puts "sending data to CCare Server" puts json # compressed_data = compress(json) request.body = json http = Net::HTTP.new uri.hostname, uri.port #, 'localhost', 8888 # uncomment if proxy is used if uri.scheme.downcase == 'https' http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE end response = http.request(request) http.finish if http.started? if !response.kind_of? Net::HTTPSuccess @logger.warn('application_insights') { "Failed to send data: #{response.message}" } end end
telemetrydata(telemetryversion, name, time, sampleRate, iKey, sdkVersion, operation_id, baseType, baseData_ver, baseData_id, gCareID, remote_ip, remote_host, forwarding_ip, client_ip, server_host, server_ip, server_hostname, useragent, session_id, timestamp, duration, responseCode, success, url, httpMethod, version, machine_from_ip, machine_from_name, machine_to_ip, machine_to_name, operation_name, roleInstance, server_port)
click to toggle source
# File lib/gcarerubymethodprofiler.rb, line 272 def telemetrydata(telemetryversion, name, time, sampleRate, iKey, sdkVersion, operation_id, baseType, baseData_ver, baseData_id, gCareID, remote_ip, remote_host, forwarding_ip, client_ip, server_host, server_ip, server_hostname, useragent, session_id, timestamp, duration, responseCode, success, url, httpMethod, version, machine_from_ip, machine_from_name, machine_to_ip, machine_to_name, operation_name, roleInstance, server_port) teledata = { 'ver' => telemetryversion, 'name' => name, 'time' => time, 'sampleRate' => sampleRate, 'iKey' => iKey, 'tags' => { 'ai' => { 'internal.sdkVersion' => sdkVersion, 'operation.id' => operation_id, 'operation.name' => operation_name, 'gcare.id' => gCareID, 'device.roleInstance' => roleInstance } } } end