delfos 0.0.1 → 0.0.2.pre.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/delfos.rb +72 -13
  3. data/lib/delfos/call_stack.rb +9 -9
  4. data/lib/delfos/call_stack/stack.rb +18 -18
  5. data/lib/delfos/file_system.rb +16 -0
  6. data/lib/delfos/file_system/app_directories.rb +42 -0
  7. data/lib/delfos/file_system/common_path.rb +17 -11
  8. data/lib/delfos/file_system/distance_calculation.rb +12 -3
  9. data/lib/delfos/file_system/path_determination.rb +4 -1
  10. data/lib/delfos/file_system/relation.rb +1 -0
  11. data/lib/delfos/method_trace.rb +59 -0
  12. data/lib/delfos/method_trace/call_handler.rb +48 -0
  13. data/lib/delfos/method_trace/code_location.rb +35 -0
  14. data/lib/delfos/method_trace/code_location/call_site.rb +38 -0
  15. data/lib/delfos/method_trace/code_location/container_method_factory.rb +71 -0
  16. data/lib/delfos/method_trace/code_location/eval_in_caller.rb +17 -0
  17. data/lib/delfos/method_trace/code_location/filename_helpers.rb +46 -0
  18. data/lib/delfos/method_trace/code_location/method.rb +58 -0
  19. data/lib/delfos/neo4j.rb +4 -4
  20. data/lib/delfos/neo4j/batch/execution.rb +30 -88
  21. data/lib/delfos/neo4j/batch/retryable.rb +101 -0
  22. data/lib/delfos/neo4j/call_site_query.rb +89 -0
  23. data/lib/delfos/neo4j/distance/call_site_fetcher.rb +1 -0
  24. data/lib/delfos/neo4j/distance/update.rb +22 -5
  25. data/lib/delfos/neo4j/live/call_site_logger.rb +17 -0
  26. data/lib/delfos/neo4j/offline/call_site_logger.rb +39 -0
  27. data/lib/delfos/neo4j/offline/importer.rb +68 -0
  28. data/lib/delfos/neo4j/query_execution/errors.rb +13 -3
  29. data/lib/delfos/neo4j/query_execution/http.rb +1 -0
  30. data/lib/delfos/neo4j/query_execution/http_query.rb +20 -15
  31. data/lib/delfos/neo4j/query_execution/sync.rb +1 -0
  32. data/lib/delfos/neo4j/query_execution/transactional.rb +24 -13
  33. data/lib/delfos/neo4j/schema.rb +5 -19
  34. data/lib/delfos/setup.rb +76 -44
  35. metadata +77 -18
  36. data/lib/delfos/method_logging.rb +0 -52
  37. data/lib/delfos/method_logging/call_site_parsing.rb +0 -74
  38. data/lib/delfos/method_logging/code_location.rb +0 -89
  39. data/lib/delfos/method_logging/method_parameters.rb +0 -53
  40. data/lib/delfos/neo4j/call_stack_query.rb +0 -88
  41. data/lib/delfos/neo4j/informer.rb +0 -128
  42. data/lib/delfos/patching/basic_object.rb +0 -14
  43. data/lib/delfos/patching/basic_object_remove.rb +0 -7
  44. data/lib/delfos/patching/method_cache.rb +0 -83
  45. data/lib/delfos/patching/method_override.rb +0 -148
  46. data/lib/delfos/patching/module_defining_methods.rb +0 -105
  47. data/lib/delfos/patching/unstubber.rb +0 -34
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BasicObject
4
- def self.method_added(*_args); end
5
-
6
- def self.singleton_method_added(*_args); end
7
- end
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
- require "Forwardable" unless defined? Forwardable
3
-
4
- module Delfos
5
- module Patching
6
- class MethodCache
7
- class << self
8
- extend Forwardable
9
-
10
- def_delegators :instance,
11
- :files_for,
12
- :append,
13
- :find
14
-
15
- def reset!
16
- @instance = nil
17
- end
18
-
19
- def instance
20
- @instance ||= new
21
- end
22
-
23
- def each_method
24
- instance.send(:added_methods).each do |klass, methods|
25
- methods.each do |k, m|
26
- class_method = !!(k[/^ClassMethod_/])
27
- yield klass, m, class_method
28
- end
29
- end
30
- end
31
- end
32
-
33
- def initialize
34
- @added_methods = {}
35
- end
36
-
37
- def files_for(klass)
38
- fetch(klass).
39
- values.
40
- map(&:source_location).
41
- compact.
42
- map(&:first).
43
- compact.
44
- uniq
45
- end
46
-
47
- def append(klass:, method:)
48
- class_method = method.respond_to?(:receiver) && method.receiver.is_a?(Class)
49
- key = key_for(class_method, method.name)
50
- m = fetch(klass)[key]
51
-
52
- fetch(klass)[key] = method if m.nil?
53
- end
54
-
55
- def find(klass:, method_name:, class_method:)
56
- key = key_for(class_method, method_name)
57
-
58
- fetch(klass)[key]
59
- end
60
-
61
- private
62
-
63
- attr_reader :added_methods
64
-
65
- def key_for(class_method, method_name)
66
- class_method ? "ClassMethod_#{method_name}" : "InstanceMethod_#{method_name}"
67
- end
68
-
69
- def fetch(klass)
70
- # Find method definitions defined in klass or its ancestors
71
- super_klass = klass.ancestors.detect do |k|
72
- (fetch_without_default(k) || {}).values.length.positive?
73
- end
74
-
75
- added_methods[(super_klass || klass).to_s] ||= {}
76
- end
77
-
78
- def fetch_without_default(klass)
79
- added_methods[klass.to_s]
80
- end
81
- end
82
- end
83
- end
@@ -1,148 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "delfos/method_logging"
4
- require "delfos/call_stack"
5
-
6
- require_relative "module_defining_methods"
7
- require_relative "unstubber"
8
-
9
- module Delfos
10
- module Patching
11
- MUTEX = Mutex.new
12
-
13
- class MethodOverride
14
- include ModuleDefiningMethods
15
-
16
- class << self
17
- def setup(klass, name, private_methods, class_method:)
18
- return if skip_meta_programming_defined_method?
19
-
20
- MUTEX.synchronize do
21
- return if Thread.current[:__delfos_disable_patching]
22
- end
23
-
24
- instance = new(klass, name, private_methods, class_method)
25
-
26
- instance.ensure_method_recorded_once!
27
- end
28
-
29
- META_PROGRAMMING_REGEX = /`define_method'\z|`attr_accessor'\z|`attr_reader'\z|`attr_writer'\z/
30
-
31
- def skip_meta_programming_defined_method?
32
- stack = caller.dup
33
-
34
- i = stack.index do |l|
35
- l["delfos/patching/basic_object.rb"]
36
- end
37
-
38
- return unless i
39
-
40
- result = stack[i + 1][META_PROGRAMMING_REGEX]
41
-
42
- return unless result
43
-
44
- Delfos.logger.debug "Skipping setting up delfos logging of method defined by #{result} #{stack[i+1]}"
45
- true
46
- end
47
-
48
-
49
- end
50
-
51
- attr_reader :klass, :name, :private_methods, :class_method
52
-
53
- def initialize(klass, name, private_methods, class_method)
54
- @klass = klass
55
- @name = name
56
- @private_methods = private_methods
57
- @class_method = class_method
58
- original_method # ensure memoized method is the original not the overridden one
59
- end
60
-
61
- def ensure_method_recorded_once!
62
- record_method! { setup }
63
- end
64
-
65
-
66
- # Redefine the method at runtime to enabling logging to Neo4j
67
- def setup
68
- cm = class_method
69
- with_stack = method(:with_stack)
70
- method_name = name
71
- om = original_method
72
-
73
- mod = module_definition(klass, name, class_method) do
74
- define_method(method_name) do |*args, **kw_args, &block|
75
- stack = caller.dup
76
- caller_binding = binding.dup
77
- parameters = Delfos::MethodLogging::MethodParameters.new(args, kw_args, block)
78
-
79
- call_site = Delfos::MethodLogging::CodeLocation.from_call_site(stack, caller_binding)
80
-
81
- if call_site
82
- Delfos::MethodLogging.log(call_site, self, om, cm, parameters)
83
- end
84
-
85
- with_stack.call(call_site) do
86
- if !kw_args.empty?
87
- super(*args, **kw_args, &block)
88
- else
89
- super(*args, &block)
90
- end
91
- end
92
- end
93
- end
94
- return unless mod
95
-
96
- if class_method
97
- klass.prepend mod
98
- else
99
- klass.instance_eval { prepend mod }
100
- end
101
- end
102
-
103
- def with_stack(call_site)
104
- return yield unless call_site
105
-
106
- begin
107
- CallStack.push(call_site)
108
- yield
109
- ensure
110
- CallStack.pop
111
- end
112
- end
113
-
114
- def original_method
115
- @original_method ||= if class_method
116
- klass.method(name)
117
- else
118
- klass.instance_method(name)
119
- end
120
- end
121
-
122
- private
123
-
124
- def record_method!
125
- return true if bail?
126
- MethodCache.append(klass: klass, method: original_method)
127
-
128
- yield
129
- end
130
-
131
- def bail?
132
- method_has_been_added? || private_method? || exclude?
133
- end
134
-
135
- def method_has_been_added?
136
- MethodCache.find(klass: klass, class_method: class_method, method_name: name)
137
- end
138
-
139
- def private_method?
140
- private_methods.include?(name.to_sym)
141
- end
142
-
143
- def exclude?
144
- ::Delfos::MethodLogging.exclude?(original_method)
145
- end
146
- end
147
- end
148
- end
@@ -1,105 +0,0 @@
1
- # frozen_string_literal: true
2
- module Delfos
3
- module Patching
4
- # containers for the individual modules created to log each method call
5
- module ClassMethodLogging
6
- end
7
-
8
- module InstanceMethodLogging
9
- end
10
-
11
- module ModuleDefiningMethods
12
- def module_definition(klass, method_name, class_method, &block)
13
- definer = ModuleDefiner.new(klass, method_name, class_method)
14
-
15
- if block_given?
16
- definer.perform(&block)
17
- else
18
- definer.perform
19
- end
20
- end
21
- end
22
-
23
- class ModuleDefiner
24
- attr_reader :klass, :method_name, :class_method
25
-
26
- def initialize(klass, method_name, class_method)
27
- @klass, @method_name, @class_method = klass, method_name, class_method
28
- end
29
-
30
- def perform(&block)
31
- safe_method_name = safe_method_name()
32
- safe_class_name = safe_class_name()
33
- module_type = class_method ? "ClassMethodLogging" : "InstanceMethodLogging"
34
- find_or_create = method(:find_or_create)
35
-
36
- m = nil
37
- Patching.const_get(module_type).instance_eval do
38
- namespace = find_or_create.call(self, safe_class_name)
39
-
40
- m = find_or_create.call(namespace, safe_method_name)
41
-
42
- m.class_eval(&block) if block_given?
43
-
44
- m
45
- end
46
- end
47
-
48
- private
49
-
50
- def safe_class_name
51
- module_safe_name(klass.name || klass.to_s)
52
- end
53
-
54
- def safe_method_name
55
- module_safe_name(method_name.to_s)
56
- end
57
-
58
- def find_or_create(container, module_name)
59
- module_name = module_name.tr(":", "_")
60
-
61
- result = container.const_get(module_name)
62
-
63
- # E.g. finding `::A' instead of Delfos::Patching::InstanceMethodLogging::A
64
- if result == klass || result.name[module_name] == result.name
65
- create(container, module_name)
66
- else
67
- result
68
- end
69
- rescue NameError => e
70
- raise unless e.message[module_name]
71
- create(container, module_name)
72
- end
73
-
74
- def create(container, module_name)
75
- m = Module.new
76
-
77
- container.const_set(module_name, m)
78
- return m
79
- rescue Exception => e
80
- m
81
- end
82
-
83
- def module_safe_name(string, _uppercase_first_letter = true)
84
- string = string.sub(/^[a-z\d]*/) { $&.capitalize }
85
-
86
- string.
87
- gsub(/(?:_|(\/))([a-z\d]*)/) { "#{Regexp.last_match(1)}#{Regexp.last_match(2).capitalize}" }.
88
- gsub("/", "::").
89
- gsub(/\=/, "Equals").
90
- gsub(/\<\=\>/, "Spaceship").
91
- gsub(/\<\=/, "LessThanOrEqualTo").
92
- gsub(/\>\=/, "GreaterThanOrEqualTo").
93
- gsub(/\#\<Class\:0x(.*)\>/) { "AnonymousClass_#{Regexp.last_match(1)}" }.
94
- gsub(/\>/, "GreaterThan").
95
- gsub(/\</, "LessThan").
96
- gsub(/!\~/, "NotMatchOperator").
97
- gsub(/\~/, "MatchOperator").
98
- gsub(/\?/, "QuestionMark").
99
- gsub(/\!$/, "Bang").
100
- gsub(/\+/, "Plus").
101
- gsub(/\[\]/, "SquareBrackets")
102
- end
103
- end
104
- end
105
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
- module Delfos
3
- module Patching
4
- class Unstubber
5
- extend ModuleDefiningMethods
6
-
7
- def self.unstub_all!
8
- MUTEX.synchronize do
9
- Thread.current[:__delfos_disable_patching] = true
10
- end
11
-
12
- MethodCache.each_method do |klass_name, method, class_method|
13
- klass = eval(klass_name)
14
-
15
- unstub!(klass, method.name, class_method)
16
- end
17
-
18
- MUTEX.synchronize do
19
- Thread.current[:__delfos_disable_patching] = false
20
- end
21
- end
22
-
23
- def self.unstub!(klass, method_name, class_method)
24
- module_definition(klass, method_name, class_method) do |m|
25
- begin
26
- remove_method :"#{method_name}"
27
- rescue NameError => e
28
- raise unless e.message["method `#{method_name}' not defined in"]
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end