activefacts-api 1.6.0 → 1.7.0
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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/activefacts-api.gemspec +3 -3
- data/lib/activefacts/tracer.rb +181 -88
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a80ac6cfb494e2b05728351858aa283a569caa5b
|
|
4
|
+
data.tar.gz: d5abea27b67b2501f16819de68c5716350423940
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 63bcb8b0e4b562ed566ea33f286469d11ba5ddce18f59cb58b66e45d5b78d94bc0643c171b8375d6d6a5d10d19aec7a5678cd42d15ab657aa53519fe05c13005
|
|
7
|
+
data.tar.gz: 8a0768e8cfe086e62ada27b327e1b9a049c4825efd0fdb925a9f6ccc85ef3873ba06a79a757ee27014bb13a86adfe6e9c4ec2374d3395f56988193523bd2f5ee
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.7.0
|
data/activefacts-api.gemspec
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: activefacts-api 1.
|
|
5
|
+
# stub: activefacts-api 1.7.0 ruby lib
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "activefacts-api"
|
|
9
|
-
s.version = "1.
|
|
9
|
+
s.version = "1.7.0"
|
|
10
10
|
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
12
12
|
s.require_paths = ["lib"]
|
|
13
13
|
s.authors = ["Clifford Heath"]
|
|
14
|
-
s.date = "2015-
|
|
14
|
+
s.date = "2015-03-06"
|
|
15
15
|
s.description = "\nThe ActiveFacts API is a Ruby DSL for managing constellations of elementary facts.\nEach fact is either existential (a value or an entity), characteristic (boolean) or\nbinary relational (A rel B). Relational facts are consistently co-referenced, so you\ncan traverse them efficiently in any direction. Each constellation maintains constraints\nover the fact population.\n"
|
|
16
16
|
s.email = "clifford.heath@gmail.com"
|
|
17
17
|
s.extra_rdoc_files = [
|
data/lib/activefacts/tracer.rb
CHANGED
|
@@ -1,9 +1,39 @@
|
|
|
1
1
|
#
|
|
2
|
-
#
|
|
3
|
-
# The trace method supports indented tracing.
|
|
4
|
-
# Set the TRACE environment variable to enable it. Search the code to find the TRACE keywords, or use "all".
|
|
2
|
+
# ActiveFacts Tracer.
|
|
5
3
|
#
|
|
6
|
-
#
|
|
4
|
+
# The trace() method supports indented tracing.
|
|
5
|
+
#
|
|
6
|
+
# The first argument is normally a symbol which is the key for related trace calls.
|
|
7
|
+
# Set the TRACE environment variable to enable it, or add trace.enable(:key) to a CLI.
|
|
8
|
+
#
|
|
9
|
+
# Each subsequent argument is either
|
|
10
|
+
# - a String (or anything that can be join()ed), or
|
|
11
|
+
# - a Proc (or anything that can be called) that returns such a string.
|
|
12
|
+
# Proc arguments will be called only if the trace key is enabled.
|
|
13
|
+
# If the key is enabled (or not present) the Trace strings will be joined and emitted.
|
|
14
|
+
#
|
|
15
|
+
# A block passed to the trace method will always be called, and trace will always return its value.
|
|
16
|
+
# Any trace emitted from within such a block will be indented if the current trace key is enabled.
|
|
17
|
+
#
|
|
18
|
+
# As a special case, a call to trace with a key ending in _ is enabled if the base key is
|
|
19
|
+
# enabled, but enabled all nested calls to trace whether or not their key is enabled.
|
|
20
|
+
#
|
|
21
|
+
# A call to trace with a key but without a block will return true if the key is enabled
|
|
22
|
+
#
|
|
23
|
+
# A call to trace with no arguments returns the Tracer object itself.
|
|
24
|
+
#
|
|
25
|
+
# Built-in trace key behaviour:
|
|
26
|
+
# help - list (at exit) all trace keys that became available during the run
|
|
27
|
+
# all - enable all trace keys
|
|
28
|
+
# keys - display trace keys on every trace message (automatically enabled by :all)
|
|
29
|
+
# debug - prepare a Ruby debugger at the start of the run, so it has the full context available
|
|
30
|
+
# firstaid - stop inside the constructor for any exception so you can inspect the local context of the cause
|
|
31
|
+
# trap - trap SIGINT (^C) in a block that allows inspecting or continuing execution (not all debuggers support this)
|
|
32
|
+
# flame - use ruby-prof-flamegraph to display the performance profile as a flame graph using SVG
|
|
33
|
+
#
|
|
34
|
+
# The debugger is chosen from ENV['DEBUG_PREFERENCE'] or the first to load of: byebug, pry. debugger, ruby-trace
|
|
35
|
+
#
|
|
36
|
+
# Copyright (c) 2009-2015 Clifford Heath. Read the LICENSE file.
|
|
7
37
|
#
|
|
8
38
|
module ActiveFacts
|
|
9
39
|
(class << self; self; end).class_eval do
|
|
@@ -12,130 +42,193 @@ module ActiveFacts
|
|
|
12
42
|
|
|
13
43
|
class Tracer
|
|
14
44
|
def initialize
|
|
45
|
+
@indent = 0 # Current nesting level of enabled trace blocks
|
|
15
46
|
@nested = false # Set when a block enables all enclosed tracing
|
|
16
|
-
@available = {}
|
|
47
|
+
@available = {} # Hash of available trace keys, accumulated during the run
|
|
17
48
|
|
|
18
|
-
# First time, initialise the tracing environment
|
|
19
|
-
@indent = 0
|
|
20
49
|
@keys = {}
|
|
21
|
-
if (e = ENV[
|
|
22
|
-
|
|
23
|
-
if @keys[:help]
|
|
24
|
-
at_exit {
|
|
25
|
-
@stderr.puts "---\nDebugging keys available: #{@available.keys.map{|s| s.to_s}.sort*", "}"
|
|
26
|
-
}
|
|
27
|
-
end
|
|
28
|
-
if @keys[:debug]
|
|
29
|
-
errors = []
|
|
30
|
-
success = false
|
|
31
|
-
(
|
|
32
|
-
[ENV["DEBUG_PREFERENCE"]].compact +
|
|
33
|
-
[
|
|
34
|
-
'byebug',
|
|
35
|
-
'pry',
|
|
36
|
-
'debugger',
|
|
37
|
-
'ruby-debug'
|
|
38
|
-
]
|
|
39
|
-
).each do |debugger|
|
|
40
|
-
begin
|
|
41
|
-
require debugger
|
|
42
|
-
puts "Loaded "+debugger
|
|
43
|
-
if debugger == 'byebug'
|
|
44
|
-
Kernel.class_eval do
|
|
45
|
-
alias_method :byebug, :debugger
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
success = true
|
|
49
|
-
break
|
|
50
|
-
rescue LoadError => e
|
|
51
|
-
errors << e
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
unless success
|
|
55
|
-
puts "Can't load any debugger, failed on:\n#{errors.inspect}"
|
|
56
|
-
end
|
|
57
|
-
::Debugger.start rescue nil
|
|
58
|
-
end
|
|
50
|
+
if (e = ENV["TRACE"])
|
|
51
|
+
e.split(/[^_a-zA-Z0-9]/).each{|k| enable(k) }
|
|
59
52
|
end
|
|
60
53
|
end
|
|
61
54
|
|
|
62
|
-
def
|
|
55
|
+
def trace(*args, &block)
|
|
56
|
+
begin
|
|
57
|
+
old_indent, old_nested, enabled = @indent, @nested, show(*args)
|
|
58
|
+
# Apologies for this monstrosity, but it reduces the steps when single-stepping:
|
|
59
|
+
block ? yield : (args.size == 0 ? self : (enabled == 1 ? true : false))
|
|
60
|
+
ensure
|
|
61
|
+
@indent, @nested = old_indent, old_nested
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def available_keys
|
|
63
66
|
@available.keys
|
|
64
67
|
end
|
|
65
68
|
|
|
66
|
-
def enabled key
|
|
69
|
+
def enabled? key
|
|
67
70
|
!key.empty? && @keys[key.to_sym]
|
|
68
71
|
end
|
|
69
72
|
|
|
70
73
|
def enable key
|
|
71
|
-
!key.
|
|
74
|
+
if !key.empty? && !@keys[s = key.to_sym]
|
|
75
|
+
@keys[s] = true
|
|
76
|
+
setup_help if s == :help
|
|
77
|
+
setup_flame if s == :flame
|
|
78
|
+
else
|
|
79
|
+
true
|
|
80
|
+
end
|
|
72
81
|
end
|
|
73
82
|
|
|
74
83
|
def disable key
|
|
75
|
-
!key.
|
|
84
|
+
!key.empty? and @keys.delete(key.to_sym)
|
|
76
85
|
end
|
|
77
86
|
|
|
78
87
|
def toggle key
|
|
79
|
-
!key.
|
|
88
|
+
if !key.empty?
|
|
89
|
+
if enabled?(key)
|
|
90
|
+
disable(key)
|
|
91
|
+
false
|
|
92
|
+
else
|
|
93
|
+
enable(key)
|
|
94
|
+
true
|
|
95
|
+
end
|
|
96
|
+
end
|
|
80
97
|
end
|
|
81
98
|
|
|
82
|
-
def
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (s = control.to_s) =~ /_\Z/
|
|
88
|
-
nested = true
|
|
89
|
-
s.sub(/_\Z/, '').to_sym # Avoid creating new strings willy-nilly
|
|
90
|
-
else
|
|
91
|
-
control
|
|
92
|
-
end
|
|
93
|
-
else
|
|
94
|
-
:all
|
|
95
|
-
end
|
|
99
|
+
def setup_help
|
|
100
|
+
at_exit {
|
|
101
|
+
$stderr.puts "---\nTracing keys available: #{@available.keys.map{|s| s.to_s}.sort*", "}"
|
|
102
|
+
}
|
|
103
|
+
end
|
|
96
104
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
def setup_flame
|
|
106
|
+
require 'ruby-prof'
|
|
107
|
+
require 'ruby-prof-flamegraph'
|
|
108
|
+
profile_result = RubyProf.start
|
|
109
|
+
at_exit {
|
|
110
|
+
profile_result2 = RubyProf.stop
|
|
111
|
+
printer = RubyProf::FlameGraphPrinter.new(profile_result2)
|
|
112
|
+
data_file = "/tmp/flamedata_#{Process.pid}.txt"
|
|
113
|
+
svg_file = "/tmp/flamedata_#{Process.pid}.svg"
|
|
114
|
+
flamegraph = File.dirname(__FILE__)+"/flamegraph.pl"
|
|
115
|
+
File.popen("tee #{data_file} | perl #{flamegraph} --countname=ms --width=4800 > #{svg_file}", "w") { |f|
|
|
116
|
+
printer.print(f, {})
|
|
117
|
+
}
|
|
118
|
+
STDERR.puts("Flame graph dumped to file:///#{svg_file}")
|
|
119
|
+
}
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def setup_debugger
|
|
123
|
+
begin
|
|
124
|
+
require 'ruby-trace '
|
|
125
|
+
Debugger.start # (:post_mortem => true) # Some Ruby versions crash on post-mortem debugging
|
|
126
|
+
rescue LoadError
|
|
127
|
+
# Ok, no debugger, tough luck.
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
(
|
|
131
|
+
[ENV["DEBUG_PREFERENCE"]].compact +
|
|
132
|
+
[
|
|
133
|
+
'byebug',
|
|
134
|
+
'pry',
|
|
135
|
+
'debugger',
|
|
136
|
+
'ruby-trace '
|
|
137
|
+
]
|
|
138
|
+
).each do |debugger|
|
|
139
|
+
begin
|
|
140
|
+
require debugger
|
|
141
|
+
if debugger == 'byebug'
|
|
142
|
+
Kernel.class_eval do
|
|
143
|
+
alias_method :byebug, :debugger
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
::Debugger.start if (const_get(::Debugger) rescue nil)
|
|
147
|
+
break
|
|
148
|
+
rescue LoadError => e
|
|
149
|
+
errors << e
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
if trace :trap
|
|
154
|
+
trap('SIGINT') do
|
|
155
|
+
puts "Stopped at:\n\t"+caller*"\n\t"
|
|
156
|
+
debugger
|
|
157
|
+
true # Stopped on SIGINT
|
|
158
|
+
end
|
|
159
|
+
end
|
|
106
160
|
end
|
|
107
161
|
|
|
162
|
+
def setup_firstaid
|
|
163
|
+
if trace :firstaid
|
|
164
|
+
puts "Preparing first aid kit"
|
|
165
|
+
::Exception.class_eval do
|
|
166
|
+
alias_method :firstaid_initialize, :initialize
|
|
167
|
+
|
|
168
|
+
def initialize *args, &b
|
|
169
|
+
send(:firstaid_initialize, *args, &b)
|
|
170
|
+
puts "Stopped due to #{self.class}: #{message} at "+caller*"\n\t"
|
|
171
|
+
debugger
|
|
172
|
+
true # Stopped in Exception constructor
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private
|
|
108
179
|
def show(*args)
|
|
109
|
-
enabled, key_to_show = selected(args)
|
|
180
|
+
enabled, key_to_show = selected?(args)
|
|
110
181
|
|
|
111
182
|
# Emit the message if enabled or a parent is:
|
|
112
183
|
if args.size > 0 && enabled == 1
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
join(' ')
|
|
184
|
+
puts "\##{key_to_show} " +
|
|
185
|
+
' '*@indent +
|
|
186
|
+
args.
|
|
187
|
+
map{|a| a.respond_to?(:call) ? a.call : a}.
|
|
188
|
+
join(' ')
|
|
119
189
|
end
|
|
120
190
|
@indent += enabled
|
|
121
191
|
enabled
|
|
122
192
|
end
|
|
123
193
|
|
|
124
|
-
def
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
194
|
+
def selected?(args)
|
|
195
|
+
# Figure out whether this trace is enabled (itself or by :all), if it nests, and if we should print the key:
|
|
196
|
+
key =
|
|
197
|
+
if Symbol === args[0]
|
|
198
|
+
control = args.shift
|
|
199
|
+
if (s = control.to_s) =~ /_\Z/
|
|
200
|
+
nested = true
|
|
201
|
+
s.sub(/_\Z/, '').to_sym # Avoid creating new strings willy-nilly
|
|
202
|
+
else
|
|
203
|
+
control
|
|
204
|
+
end
|
|
205
|
+
else
|
|
206
|
+
:all
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
@available[key] ||= key # Remember that this trace was requested, for help
|
|
210
|
+
enabled = @nested || # This trace is enabled because it's in a nested block
|
|
211
|
+
@keys[key] || # This trace is enabled in its own right
|
|
212
|
+
@keys[:all] # This trace is enabled because all are
|
|
213
|
+
@nested = nested
|
|
214
|
+
[
|
|
215
|
+
(enabled ? 1 : 0),
|
|
216
|
+
@keys[:keys] || @keys[:all] ? " %-15s"%control : nil
|
|
217
|
+
]
|
|
131
218
|
end
|
|
219
|
+
|
|
132
220
|
end
|
|
133
221
|
end
|
|
134
222
|
|
|
223
|
+
# Make the trace method globally available:
|
|
135
224
|
class Object
|
|
136
225
|
def trace *args, &block
|
|
137
226
|
(ActiveFacts.tracer ||= ActiveFacts::Tracer.new).trace(*args, &block)
|
|
138
227
|
end
|
|
139
228
|
end
|
|
140
229
|
|
|
141
|
-
|
|
230
|
+
# Load the ruby debugger before everything else, if requested
|
|
231
|
+
if trace(:debug) or trace(:firstaid) or trace(:trap)
|
|
232
|
+
trace.setup_debugger
|
|
233
|
+
trace.setup_firstaid
|
|
234
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activefacts-api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Clifford Heath
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-03-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rbtree-pure
|