activefacts-api 1.6.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|