class Neolytics::Recorder
Constants
- CLEAR
- CYAN
- GREEN
Public Class Methods
new(neo4j_session)
click to toggle source
# File lib/neolytics/recorder.rb, line 8 def initialize(neo4j_session) @neo4j_session = neo4j_session @neo4apis_session = Neo4Apis::Neolytics.new(neo4j_session) create_indexes end
Public Instance Methods
create_indexes()
click to toggle source
# File lib/neolytics/recorder.rb, line 14 def create_indexes @neo4j_session.query('CREATE INDEX ON :ASTNode(file_path)') @neo4j_session.query('CREATE INDEX ON :ASTNode(first_line)') @neo4j_session.query('CREATE INDEX ON :ASTNode(type)') @neo4j_session.query('CREATE INDEX ON :ASTNode(name)') @neo4j_session.query('CREATE INDEX ON :TracePoint(path)') @neo4j_session.query('CREATE INDEX ON :TracePoint(event)') @neo4j_session.query('CREATE INDEX ON :TracePoint(lineno)') @neo4j_session.query('CREATE INDEX ON :TracePoint(defined_class)') @neo4j_session.query('CREATE INDEX ON :TracePoint(method_id)') @neo4j_session.query('CREATE INDEX ON :TracePoint(execution_index)') end
record(&block)
click to toggle source
# File lib/neolytics/recorder.rb, line 28 def record(&block) @neo4apis_session.batch do record_execution_trace do begin block.call rescue Exception => e nil end end @neo4apis_session.instance_variable_get('@buffer').flush query = <<QUERY MATCH (tp:TracePoint) WHERE NOT(tp.path IS NULL) AND NOT(tp.path = '(eval)' OR tp.path = '(irb)') RETURN DISTINCT tp.path AS path QUERY file_paths = @neo4j_session.query(query).map(&:path) file_paths.each(&method(:record_ast)) link_query = <<QUERY MATCH (tp:TracePoint) WITH tp, tp.lineno AS lineno, tp.path AS path, tp.method_id AS method_id MATCH (node:ASTNode {type: 'def'}) USING INDEX node:ASTNode(name) WHERE node.name = method_id AND node.file_path = path AND node.first_line = lineno MERGE (tp)-[:HAS_AST_NODE]->(node) QUERY @neo4j_session.query(link_query) end end
record_ast(file_path)
click to toggle source
# File lib/neolytics/recorder.rb, line 63 def record_ast(file_path) full_path = Pathname.new(file_path).realpath.to_s code = File.read(full_path) require 'parser/current' begin root = Parser::CurrentRuby.parse(code) rescue EncodingError return end file_node = @neo4apis_session.import :File, full_path, code node_node = @neo4apis_session.import :ASTNode, root, file_node end
record_execution_trace() { || ... }
click to toggle source
# File lib/neolytics/recorder.rb, line 80 def record_execution_trace execution_index = 0 indent = 0 output = '' last_tracepoint_node = nil last_start_time = nil ancestor_stack = [] run_time_stack = [] total_run_time_stack = [] last_tracepoint_end_time = nil last_run_time = nil trace = TracePoint.new do |tp| begin last_run_time = 1_000_000.0 * (Time.now - last_tracepoint_end_time) if last_tracepoint_end_time next if tp.path.match(%r{/neolytics/}) start = Time.now output << tracepoint_string(tp, indent) last_method_time = nil if [:call, :c_call].include?(tp.event) run_time_stack.push(0) total_run_time_stack.push(0) elsif [:return, :c_return].include?(tp.event) last_method_time = run_time_stack.pop last_method_total_time = total_run_time_stack.pop else #puts "total_run_time_stack: #{total_run_time_stack.inspect}" #puts "increment by #{last_run_time}" if run_time_stack[-1] && last_run_time run_time_stack[-1] += last_run_time total_run_time_stack.map! { |i| i + last_run_time } end end associated_call = nil if [:return, :c_return].include?(tp.event) && indent.nonzero? indent -= 1 associated_call = ancestor_stack.pop elsif [:call, :c_call].include?(tp.event) indent += 1 end last_tracepoint_node = @neo4apis_session.import :TracePoint, tp, last_method_time, last_method_total_time, (execution_index += 1), last_tracepoint_node, ancestor_stack.last, associated_call if [:call, :c_call].include?(tp.event) ancestor_stack.push(last_tracepoint_node) end stop = Time.now diff = stop - start if diff > 0.5 puts "time: #{diff}" puts "tp: #{tp.inspect}" end last_tracepoint_end_time = Time.now rescue Exception => e puts 'EXCEPTION!!' puts e.message puts e.backtrace exit! end end trace.enable yield ensure trace.disable puts output end
Private Instance Methods
tracepoint_string(tp, indent)
click to toggle source
# File lib/neolytics/recorder.rb, line 166 def tracepoint_string(tp, indent) parts = [] parts << "#{'| ' * indent}" parts << "#{CYAN if tp.event == :call}%-8s#{CLEAR}" parts << "%s:%-4d %-18s\n" parts.join(' ') % [tp.event, tp.path, tp.lineno, tp.defined_class.to_s + '#' + GREEN + tp.method_id.to_s + CLEAR] end