wagn 1.14.7 → 1.14.8
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/JASMINE_RAILS_TEST.md +16 -0
- data/VERSION +1 -1
- data/db/bootstrap/card_actions.yml +501 -480
- data/db/bootstrap/card_acts.yml +1 -1
- data/db/bootstrap/card_changes.yml +1815 -1752
- data/db/bootstrap/cards.yml +1500 -1443
- data/db/migrate/20141121172918_rename_card_migration_table.rb +8 -1
- data/lib/card/chunk.rb +0 -1
- data/lib/card/content.rb +1 -1
- data/lib/card/format.rb +6 -4
- data/lib/card/generators/card_migration/card_migration_generator.rb +1 -2
- data/lib/card/loader.rb +4 -0
- data/lib/card/set.rb +21 -7
- data/lib/card/set_pattern.rb +38 -5
- data/lib/wagn.rb +3 -3
- data/lib/wagn/core_migration.rb +1 -15
- data/lib/wagn/generators/wagn/templates/Rakefile +0 -1
- data/lib/wagn/log.rb +297 -94
- data/lib/wagn/migration.rb +53 -24
- data/lib/wagn/tasks/wagn.rake +17 -19
- data/mod/01_core/set/all/collection.rb +1 -1
- data/mod/01_core/set/all/content.rb +5 -2
- data/mod/01_core/set/all/fetch.rb +35 -35
- data/mod/01_core/set/all/trash.rb +3 -3
- data/mod/01_core/set/all/type.rb +7 -4
- data/mod/01_core/spec/set/all/tracked_attributes_spec.rb +1 -1
- data/mod/01_core/spec/set/all/trash_spec.rb +19 -0
- data/mod/02_basic_types/spec/set/type/pointer_spec.rb +13 -3
- data/mod/03_machines/set/type/coffee_script.rb +5 -3
- data/mod/03_machines/set/type/css.rb +4 -2
- data/mod/03_machines/set/type/java_script.rb +5 -4
- data/mod/04_settings/set/right/style.rb +3 -2
- data/mod/05_email/format/email_text_format.rb +4 -0
- data/mod/05_email/set/all/email_text.rb +1 -2
- data/mod/05_email/set/right/bcc.rb +8 -4
- data/mod/05_email/set/type/email_template.rb +20 -20
- data/mod/05_standard/set/all/attach.rb +0 -1
- data/mod/05_standard/set/type/basic.rb +3 -1
- data/mod/05_standard/set/type/html.rb +7 -5
- data/mod/05_standard/spec/set/type/email_template_spec.rb +166 -99
- data/public/assets/ace/ext-searchbox.js +409 -0
- data/spec/lib/card/set_pattern_spec.rb +18 -1
- data/spec/lib/wagn/log_spec.rb +217 -56
- data/test/fixtures/card_actions.yml +945 -924
- data/test/fixtures/card_acts.yml +101 -101
- data/test/fixtures/card_changes.yml +3764 -3701
- data/test/fixtures/cards.yml +2012 -1955
- metadata +4 -2
@@ -1,7 +1,14 @@
|
|
1
1
|
class RenameCardMigrationTable < ActiveRecord::Migration
|
2
2
|
def self.up
|
3
|
-
|
3
|
+
if ActiveRecord::Base.connection.table_exists? :schema_migrations_cards
|
4
|
+
rename_table :schema_migrations_cards, :schema_migrations_core_cards
|
5
|
+
else
|
6
|
+
create_table "schema_migrations_core_cards", :id => false, :force => true do |t|
|
7
|
+
t.string "version", :null => false
|
8
|
+
end
|
9
|
+
end
|
4
10
|
end
|
11
|
+
|
5
12
|
def self.down
|
6
13
|
rename_table :schema_migrations_core_cards, :schema_migrations_cards
|
7
14
|
end
|
data/lib/card/chunk.rb
CHANGED
@@ -47,7 +47,6 @@ class Card
|
|
47
47
|
register_list :default, [ :URI, :HostURI, :EmailURI, :EscapedLiteral, :Include, :Link ]
|
48
48
|
register_list :references, [ :EscapedLiteral, :Include, :Link ]
|
49
49
|
register_list :inclusion_only, [ :Include ]
|
50
|
-
register_list :inclusion_and_link, [ :Include, :Link ]
|
51
50
|
|
52
51
|
class Abstract
|
53
52
|
class_attribute :config
|
data/lib/card/content.rb
CHANGED
data/lib/card/format.rb
CHANGED
@@ -26,11 +26,13 @@ class Card
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def format_class_name format
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
format = format.to_s
|
30
|
+
format = '' if format == 'base'
|
31
|
+
format = @@aliases[ format ] if @@aliases[ format ]
|
32
|
+
"#{ format.camelize }Format"
|
32
33
|
end
|
33
34
|
|
35
|
+
|
34
36
|
|
35
37
|
def extract_class_vars view, opts
|
36
38
|
return unless opts.present?
|
@@ -183,7 +185,7 @@ class Card
|
|
183
185
|
@current_view = view = ok_view canonicalize_view( view ), args
|
184
186
|
args = default_render_args view, args
|
185
187
|
with_inclusion_mode view do
|
186
|
-
Wagn.with_logging :view, view, :context=>card.name, :details=>args do
|
188
|
+
Wagn.with_logging :view, :message=>view, :context=>card.name, :details=>args do
|
187
189
|
send "_view_#{ view }", args
|
188
190
|
end
|
189
191
|
end
|
@@ -8,8 +8,7 @@ class CardMigrationGenerator < ActiveRecord::Generators::Base
|
|
8
8
|
desc: "Create card migration for wagn core"
|
9
9
|
|
10
10
|
def create_migration_file
|
11
|
-
|
12
|
-
root = Wagn::Migration.paths(migration_type).first
|
11
|
+
root = options['core'] ? Wagn::CoreMigration.paths.first : Wagn::Migration.paths.first
|
13
12
|
set_local_assigns!
|
14
13
|
migration_template @migration_template, File.join( root, "#{file_name}.rb")
|
15
14
|
end
|
data/lib/card/loader.rb
CHANGED
data/lib/card/set.rb
CHANGED
@@ -107,10 +107,22 @@ class Card
|
|
107
107
|
|
108
108
|
end
|
109
109
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
110
|
+
|
111
|
+
def format *format_names, &block
|
112
|
+
if format_names.empty?
|
113
|
+
format_names = [:base]
|
114
|
+
elsif format_names.first == :all
|
115
|
+
format_names = Card::Format.registered.reject {|f| Card::Format.aliases[f]}
|
116
|
+
end
|
117
|
+
format_names.each do |f|
|
118
|
+
define_on_format f, &block
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def define_on_format format_name=:base, &block
|
123
|
+
klass = Card::Format.format_class_name format_name # format class name, eg. HtmlFormat
|
124
|
+
mod = const_get_or_set klass do # called on current set module, eg Card::Set::Type::Pointer
|
125
|
+
m = Module.new # yielding set format module, eg Card::Set::Type::Pointer::HtmlFormat
|
114
126
|
register_set_format Card.const_get(klass), m
|
115
127
|
m.extend Card::Set::Format
|
116
128
|
m
|
@@ -136,7 +148,7 @@ class Card
|
|
136
148
|
|
137
149
|
define_method event do
|
138
150
|
run_callbacks event do
|
139
|
-
Wagn.with_logging :event, event, :context=>self.name, :details=>opts do
|
151
|
+
Wagn.with_logging :event, :message=>event, :context=>self.name, :details=>opts do
|
140
152
|
send final_method
|
141
153
|
end
|
142
154
|
end
|
@@ -200,9 +212,11 @@ class Card
|
|
200
212
|
# FIXME - this does not properly handle anchorless sets
|
201
213
|
# There are special hacks for *all, but others (like *rstar) will not be found by
|
202
214
|
# include_set_modules, which will look for Card::Set::Rstar, not Card::Set::Rstar::Blah
|
203
|
-
|
215
|
+
# This issue appears to be addressed by making the entries, in modules arrays.
|
216
|
+
# If yes remove this comment.
|
217
|
+
|
204
218
|
to_file = "#{Wagn.paths['tmp/set'].first}/#{set_pattern}/#{seq}-#{anchors.join '-'}.rb"
|
205
|
-
anchor_modules = anchors.map { |a| "module #{a.camelize};" }.join
|
219
|
+
anchor_modules = anchors.map { |a| "module #{a.camelize};" }.join # use explicit '', not $,
|
206
220
|
file_content = <<EOF
|
207
221
|
# -*- encoding : utf-8 -*-
|
208
222
|
class Card; module Set; module #{set_pattern.camelize}; #{anchor_modules}
|
data/lib/card/set_pattern.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
class Card
|
2
|
+
|
2
3
|
class SetPattern
|
3
4
|
|
4
5
|
class << self
|
@@ -38,11 +39,11 @@ class Card
|
|
38
39
|
def pattern_applies? card
|
39
40
|
junction_only? ? card.cardname.junction? : true
|
40
41
|
end
|
41
|
-
|
42
|
+
|
42
43
|
def anchor_parts_count
|
43
44
|
@anchor_parts_count ||= ( anchorless? ? 0 : 1 )
|
44
45
|
end
|
45
|
-
|
46
|
+
|
46
47
|
def write_tmp_file pattern_code, from_file, seq
|
47
48
|
to_file = "#{Wagn.paths['tmp/set_pattern'].first}/#{seq}-#{pattern_code}.rb"
|
48
49
|
klass = "Card::#{pattern_code.camelize}Set"
|
@@ -91,12 +92,16 @@ EOF
|
|
91
92
|
end
|
92
93
|
end
|
93
94
|
|
95
|
+
def lookup_module_list modules_hash
|
96
|
+
module_key && modules_hash[ module_key ]
|
97
|
+
end
|
98
|
+
|
94
99
|
def module_list
|
95
|
-
|
100
|
+
lookup_module_list Card::Set.modules[ :nonbase ]
|
96
101
|
end
|
97
102
|
|
98
103
|
def format_module_list klass
|
99
|
-
|
104
|
+
hash = Card::Set.modules[ :nonbase_format ][ klass ] and lookup_module_list hash
|
100
105
|
end
|
101
106
|
|
102
107
|
def anchor_codenames
|
@@ -130,6 +135,34 @@ EOF
|
|
130
135
|
[ @anchor_id, self.class.pattern_code ].map( &:to_s ) * '+'
|
131
136
|
end
|
132
137
|
end
|
133
|
-
|
138
|
+
end
|
139
|
+
|
140
|
+
class TypeSet < SetPattern
|
141
|
+
def initialize card
|
142
|
+
super
|
143
|
+
@inherit_card = card unless module_key
|
144
|
+
end
|
145
|
+
|
146
|
+
def lookup_inherited_key
|
147
|
+
return unless @inherit_card
|
148
|
+
card, @inherit_card = @inherit_card, nil
|
149
|
+
|
150
|
+
default_rule = card.rule_card(:default) and
|
151
|
+
type_code = default_rule.type_code and
|
152
|
+
#default_rule.cardname.size > 2 and
|
153
|
+
#default_rule.left.right.codename == self.class.pattern_code
|
154
|
+
mod_key = "Type::#{type_code.to_s.camelize}" and
|
155
|
+
( Card::Set.modules[:nonbase_format].values +
|
156
|
+
[Card::Set.modules[:nonbase]] ).any?{|hash| hash[mod_key]} and
|
157
|
+
mod_key
|
158
|
+
end
|
159
|
+
|
160
|
+
def inherited_key
|
161
|
+
(defined? @inherited_key) ? @inherited_key : @inherited_key = lookup_inherited_key
|
162
|
+
end
|
163
|
+
|
164
|
+
def lookup_module_list modules_hash
|
165
|
+
module_key ? modules_hash[ module_key ] : inherited_key && modules_hash[ inherited_key ]
|
166
|
+
end
|
134
167
|
end
|
135
168
|
end
|
data/lib/wagn.rb
CHANGED
@@ -24,9 +24,9 @@ module Wagn
|
|
24
24
|
WAGN_GEM_ROOT
|
25
25
|
end
|
26
26
|
|
27
|
-
def with_logging method,
|
28
|
-
if
|
29
|
-
Wagn::Log::Performance.with_timer(method,
|
27
|
+
def with_logging method, opts, &block
|
28
|
+
if Wagn::Log::Performance.enabled_method? method
|
29
|
+
Wagn::Log::Performance.with_timer(method, opts) do
|
30
30
|
block.call
|
31
31
|
end
|
32
32
|
else
|
data/lib/wagn/core_migration.rb
CHANGED
@@ -1,19 +1,5 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
|
3
3
|
class Wagn::CoreMigration < Wagn::Migration
|
4
|
-
|
5
|
-
Wagn::Migration.paths :core_cards
|
6
|
-
end
|
7
|
-
|
8
|
-
def schema_mode
|
9
|
-
Wagn::Migration.schema_mode :core_cards
|
10
|
-
end
|
11
|
-
|
12
|
-
def import_json filename
|
13
|
-
Wagn.config.action_mailer.perform_deliveries = false
|
14
|
-
raw_json = File.read( data_path filename )
|
15
|
-
json = JSON.parse raw_json
|
16
|
-
Card.merge_list json["card"]["value"], :output_file=>File.join(data_path,"unmerged_#{ filename }")
|
17
|
-
#fixme - output file should not be in gem!
|
18
|
-
end
|
4
|
+
@type = :core_cards
|
19
5
|
end
|
data/lib/wagn/log.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
require 'csv'
|
2
2
|
|
3
|
+
|
3
4
|
class Wagn::Log
|
4
5
|
|
5
6
|
class Request
|
7
|
+
|
6
8
|
def self.path
|
7
9
|
path = (Wagn.paths['request_log'] && Wagn.paths['request_log'].first) || File.dirname(Wagn.paths['log'].first)
|
8
10
|
filename = "#{Date.today}_#{Rails.env}.csv"
|
9
11
|
File.join path, filename
|
10
12
|
end
|
11
|
-
|
13
|
+
|
12
14
|
def self.write_log_entry controller
|
13
15
|
return if controller.env["REQUEST_URI"] =~ %r{^/files?/}
|
14
16
|
|
@@ -34,24 +36,230 @@ class Wagn::Log
|
|
34
36
|
end
|
35
37
|
|
36
38
|
end
|
37
|
-
|
39
|
+
|
38
40
|
|
39
41
|
class Performance
|
42
|
+
# To enable logging add a performance_logger hash to your configuration and change the log_level to :wagn
|
43
|
+
# config options
|
44
|
+
#
|
45
|
+
# Example:
|
46
|
+
# config.performance_logger = {
|
47
|
+
# :min_time => 100, # show only method calls that are slower than 100ms
|
48
|
+
# :max_depth => 3, # show nested method calls only up to depth 3
|
49
|
+
# :details=> true # show method arguments and sql
|
50
|
+
# :methods => [:event, :search, :fetch, :view], # choose methods to log
|
51
|
+
# }
|
52
|
+
#
|
53
|
+
# If you give :methods a hash you can log arbitrary methods. The syntax is as follows:
|
54
|
+
# class => method type => method name => log options
|
55
|
+
#
|
56
|
+
# Example:
|
57
|
+
# Card => {
|
58
|
+
# :instance => [ :fetch, :search ],
|
59
|
+
# :singleton => { :fetch => { :title => 'Card.fetch' } },
|
60
|
+
# :all => {
|
61
|
+
# :fetch => {
|
62
|
+
# :message => 2 # use second argument passed to fetch
|
63
|
+
# :details => :to_s # use return value of to_s in method context
|
64
|
+
# :title => proc { |method_context| method_context.name }
|
65
|
+
# },
|
66
|
+
# },
|
67
|
+
# },
|
68
|
+
#
|
69
|
+
# class, method type and log options are optional.
|
70
|
+
# Default values are 'Card', ':all' and { :title => method name, :message => first argument, :details=> remaining arguments }.
|
71
|
+
# For example [:fetch] is equivalent to Card => { :all => { :fetch => { :message=>1, :details=>1..-1 } }
|
72
|
+
|
73
|
+
DEFAULT_CLASS = Card
|
74
|
+
DEFAULT_METHOD_TYPE = :all
|
75
|
+
DEFAULT_METHOD_OPTIONS = {
|
76
|
+
:title => :method_name,
|
77
|
+
:message => 1,
|
78
|
+
:details => 1..-1,
|
79
|
+
:context => nil
|
80
|
+
}
|
81
|
+
|
82
|
+
SPECIAL_METHODS = [:search, :view, :event] # these methods have already a Wagn.with_logging block
|
83
|
+
# we don't have to monkey patch them, only turn the logging on with adding the symbol to the methods hash
|
84
|
+
|
85
|
+
|
86
|
+
|
40
87
|
TAB_SIZE = 3
|
41
88
|
@@log = []
|
42
89
|
@@context_entries = []
|
43
90
|
@@active_entries = []
|
44
91
|
@@current_level = 0
|
45
|
-
|
46
|
-
|
47
|
-
|
92
|
+
|
93
|
+
|
94
|
+
class << self
|
95
|
+
def load_config args
|
96
|
+
@details = args[:details] || false
|
97
|
+
@max_depth = args[:max_depth] || false
|
98
|
+
@min_time = args[:min_time] || false
|
99
|
+
@enabled_methods = ::Set.new
|
100
|
+
prepare_methods_for_logging args[:methods] if args[:methods]
|
101
|
+
end
|
102
|
+
|
103
|
+
def start args={}
|
104
|
+
@@current_level = 0
|
105
|
+
@@log = []
|
106
|
+
@@context_entries = []
|
107
|
+
@@active_entries = []
|
108
|
+
@@first_entry = new_entry(args)
|
109
|
+
end
|
110
|
+
|
111
|
+
def stop
|
112
|
+
while (entry = @@context_entries.pop) do
|
113
|
+
finish_entry entry
|
114
|
+
end
|
115
|
+
if @@first_entry
|
116
|
+
@@first_entry.save_duration
|
117
|
+
finish_entry @@first_entry
|
118
|
+
end
|
119
|
+
print_log
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def with_timer method, args, &block
|
124
|
+
if args[:context]
|
125
|
+
|
126
|
+
# if the previous context was created by an entry on the same level
|
127
|
+
# then finish the current context if it's a different context
|
128
|
+
if @@context_entries.last && @@current_level == @@context_entries.last.level+1 &&
|
129
|
+
args[:context] != @@context_entries.last.context
|
130
|
+
finish_entry @@context_entries.pop
|
131
|
+
end
|
132
|
+
|
133
|
+
# start new context if it's different from the parent context
|
134
|
+
if @@context_entries.empty? || args[:context] != @@context_entries.last.context
|
135
|
+
@@context_entries << new_entry( :title=>'process', :message=>args[:context], :context=>args[:context] )
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
timer = new_entry args.merge(:method=>method )
|
140
|
+
begin
|
141
|
+
result = block.call
|
142
|
+
ensure
|
143
|
+
timer.save_duration
|
144
|
+
finish_entry timer
|
145
|
+
|
146
|
+
# finish all deeper nested contexts
|
147
|
+
while @@context_entries.last && @@context_entries.last.level >= @@current_level
|
148
|
+
finish_entry @@context_entries.pop
|
149
|
+
end
|
150
|
+
# we don't know whether the next entry will belong to the same context or will start a new one
|
151
|
+
# so we save the time
|
152
|
+
@@context_entries.last.save_duration if @@context_entries.last
|
153
|
+
end
|
154
|
+
result
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
def enable_method method_name
|
159
|
+
@enabled_methods ||= ::Set.new
|
160
|
+
@enabled_methods << method_name
|
161
|
+
end
|
162
|
+
|
163
|
+
def enabled_method? method_name
|
164
|
+
@enabled_methods && @enabled_methods.include?(method_name)
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
def print_log
|
170
|
+
@@log.each do |entry|
|
171
|
+
Rails.logger.wagn entry.to_s! if entry.valid
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def new_entry args
|
176
|
+
args.delete(:details) unless @details
|
177
|
+
level = @@current_level
|
178
|
+
|
179
|
+
last_entry = @@active_entries.last
|
180
|
+
parent = if last_entry
|
181
|
+
last_entry.level == level ? last_entry.parent : last_entry
|
182
|
+
end
|
183
|
+
|
184
|
+
@@log << Wagn::Log::Performance::Entry.new(parent, level, args )
|
185
|
+
@@current_level += 1
|
186
|
+
@@active_entries << @@log.last
|
187
|
+
|
188
|
+
@@log.last
|
189
|
+
end
|
190
|
+
|
191
|
+
def finish_entry entry
|
192
|
+
if (@max_depth && entry.level > @max_depth) || (@min_time && entry.duration < @min_time)
|
193
|
+
entry.delete
|
194
|
+
end
|
195
|
+
@@active_entries.pop
|
196
|
+
@@current_level -= 1
|
197
|
+
end
|
198
|
+
|
199
|
+
def prepare_methods_for_logging args
|
200
|
+
classes = hashify_and_verify_keys( args, DEFAULT_CLASS ) do |key|
|
201
|
+
key.kind_of?(Class) || key.kind_of?(Module)
|
202
|
+
end
|
203
|
+
|
204
|
+
classes.each do |klass, method_types|
|
205
|
+
klass.extend BigBrother # add watch methods
|
206
|
+
|
207
|
+
method_types = hashify_and_verify_keys( method_types, DEFAULT_METHOD_TYPE ) do |key|
|
208
|
+
[:all, :instance, :singleton].include? key
|
209
|
+
end
|
210
|
+
|
211
|
+
method_types.each do |method_type, methods|
|
212
|
+
methods = hashify_and_verify_keys methods
|
213
|
+
methods.each do |method_name, options|
|
214
|
+
klass.watch_method method_name, method_type, DEFAULT_METHOD_OPTIONS.merge(options)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
def hashify_and_verify_keys args, default_key=nil
|
223
|
+
if default_key
|
224
|
+
case args
|
225
|
+
when Symbol
|
226
|
+
{ default_key => [ args ] }
|
227
|
+
when Array
|
228
|
+
{ default_key => args }
|
229
|
+
when Hash
|
230
|
+
if block_given?
|
231
|
+
args.keys.select{ |key| !(yield(key)) }.each do |key|
|
232
|
+
args[default_key] = { key => args[key] }
|
233
|
+
args.delete key
|
234
|
+
end
|
235
|
+
end
|
236
|
+
args
|
237
|
+
end
|
238
|
+
else
|
239
|
+
case args
|
240
|
+
when Symbol
|
241
|
+
{ args => {} }
|
242
|
+
when Array
|
243
|
+
args.inject({}) do |h, key|
|
244
|
+
h[key] = {}
|
245
|
+
h
|
246
|
+
end
|
247
|
+
else
|
248
|
+
args
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
48
253
|
end
|
254
|
+
|
255
|
+
|
49
256
|
class Entry
|
50
257
|
attr_accessor :level, :valid, :context, :parent, :children_cnt, :duration
|
51
|
-
|
258
|
+
|
52
259
|
def initialize( parent, level, args )
|
53
260
|
@start = Time.new
|
54
|
-
@message = "#{ args[:
|
261
|
+
@message = "#{ args[:title] || args[:method] || '' }"
|
262
|
+
@message += ": #{ args[:message] }" if args[:message]
|
55
263
|
@details = args[:details]
|
56
264
|
@context = args[:context]
|
57
265
|
@level = level
|
@@ -59,7 +267,7 @@ class Wagn::Log
|
|
59
267
|
@valid = true
|
60
268
|
@parent = parent
|
61
269
|
@children_cnt = 0
|
62
|
-
if @parent
|
270
|
+
if @parent
|
63
271
|
@parent.add_children
|
64
272
|
#@sibling_nr = @parent.children_cnt
|
65
273
|
end
|
@@ -68,19 +276,19 @@ class Wagn::Log
|
|
68
276
|
def add_children
|
69
277
|
@children_cnt += 1
|
70
278
|
end
|
71
|
-
|
279
|
+
|
72
280
|
def delete_children
|
73
281
|
@children_cnt -= 1
|
74
282
|
end
|
75
|
-
|
283
|
+
|
76
284
|
def has_younger_siblings?
|
77
285
|
@parent && @parent.children_cnt > 0 #@sibling_nr
|
78
286
|
end
|
79
|
-
|
287
|
+
|
80
288
|
def save_duration
|
81
289
|
@duration = (Time.now - @start) * 1000
|
82
290
|
end
|
83
|
-
|
291
|
+
|
84
292
|
def delete
|
85
293
|
@valid = false
|
86
294
|
@parent.delete_children if @parent
|
@@ -90,11 +298,11 @@ class Wagn::Log
|
|
90
298
|
# deletes the children counts in order to print the tree;
|
91
299
|
# must be called in the right order
|
92
300
|
#
|
93
|
-
# More robuts but more expensive approach: use @sibling_nr instead of counting @children_cnt down,
|
94
|
-
# but @sibling_nr has to be updated for all siblings of an entry if the entry gets deleted due to
|
301
|
+
# More robuts but more expensive approach: use @sibling_nr instead of counting @children_cnt down,
|
302
|
+
# but @sibling_nr has to be updated for all siblings of an entry if the entry gets deleted due to
|
95
303
|
# min_time or max_depth restrictions in the config, so we have to save all children relations for that
|
96
304
|
def to_s!
|
97
|
-
@to_s ||= begin
|
305
|
+
@to_s ||= begin
|
98
306
|
msg = indent
|
99
307
|
msg += if @duration
|
100
308
|
"(%d.2ms) #{@message}" % @duration
|
@@ -108,8 +316,8 @@ class Wagn::Log
|
|
108
316
|
msg
|
109
317
|
end
|
110
318
|
end
|
111
|
-
|
112
|
-
private
|
319
|
+
|
320
|
+
private
|
113
321
|
|
114
322
|
def indent link=true
|
115
323
|
@indent ||= begin
|
@@ -119,12 +327,12 @@ class Wagn::Log
|
|
119
327
|
res = ' '
|
120
328
|
res += (1..level-1).inject('') do |msg, index|
|
121
329
|
if younger_siblings[index]
|
122
|
-
msg << '|' + ' ' * (TAB_SIZE-1)
|
330
|
+
msg << '|' + ' ' * (TAB_SIZE-1)
|
123
331
|
else
|
124
332
|
msg << ' ' * TAB_SIZE
|
125
333
|
end
|
126
334
|
end
|
127
|
-
|
335
|
+
|
128
336
|
res += link ? '|--' : ' '
|
129
337
|
end
|
130
338
|
end
|
@@ -139,99 +347,94 @@ class Wagn::Log
|
|
139
347
|
end
|
140
348
|
res.reverse
|
141
349
|
end
|
142
|
-
|
350
|
+
|
143
351
|
end
|
352
|
+
|
353
|
+
|
354
|
+
module BigBrother
|
144
355
|
|
356
|
+
def watch_method method_name, method_type=:all, options={}
|
357
|
+
Wagn::Log::Performance.enable_method method_name
|
145
358
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
154
|
-
|
155
|
-
def stop
|
156
|
-
while (entry = @@context_entries.pop) do
|
157
|
-
finish_entry entry
|
359
|
+
if !SPECIAL_METHODS.include? method_name
|
360
|
+
if method_type == :all || method_type == :singleton
|
361
|
+
add_singleton_logging method_name, options
|
362
|
+
end
|
363
|
+
if method_type == :all || method_type == :instance
|
364
|
+
add_instance_logging method_name, options
|
365
|
+
end
|
158
366
|
end
|
159
|
-
|
160
|
-
|
161
|
-
|
367
|
+
end
|
368
|
+
|
369
|
+
def watch_instance_method *names
|
370
|
+
names.each do |name|
|
371
|
+
watch_method name, :instance
|
162
372
|
end
|
163
|
-
print_log
|
164
373
|
end
|
165
|
-
|
166
|
-
def
|
167
|
-
|
168
|
-
|
169
|
-
# if the previous context was created by an entry on the same level
|
170
|
-
# the finish the context if it's a different context
|
171
|
-
if @@context_entries.last && @@current_level == @@context_entries.last.level+1 &&
|
172
|
-
args[:context] != @@context_entries.last.context
|
173
|
-
finish_entry @@context_entries.pop
|
174
|
-
end
|
175
|
-
|
176
|
-
# start new context if it's different from the parent context
|
177
|
-
if @@context_entries.empty? || args[:context] != @@context_entries.last.context
|
178
|
-
@@context_entries << new_entry( :method=>'process', :message=>args[:context], :context=>args[:context] )
|
179
|
-
end
|
374
|
+
|
375
|
+
def watch_singleton_method *names
|
376
|
+
names.each do |name|
|
377
|
+
watch_method name, :singleton
|
180
378
|
end
|
379
|
+
end
|
181
380
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
ensure
|
186
|
-
timer.save_duration
|
187
|
-
finish_entry timer
|
381
|
+
def watch_all_instance_methods
|
382
|
+
watch_instance_method *instance_methods
|
383
|
+
end
|
188
384
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
385
|
+
def watch_all_singleton_methods
|
386
|
+
fragile_methods = [:default_scope, :default_scopes, :default_scopes=] # if I touch these methods ActiveRecord breaks
|
387
|
+
watch_singleton_method *(singleton_methods - fragile_methods)
|
388
|
+
end
|
389
|
+
|
390
|
+
def watch_all_methods
|
391
|
+
watch_all_instance_methods
|
392
|
+
watch_all_singleton_methods
|
393
|
+
end
|
394
|
+
|
395
|
+
private
|
396
|
+
|
397
|
+
def add_singleton_logging method_name, options
|
398
|
+
return unless singleton_class.method_defined? method_name
|
399
|
+
m = method(method_name)
|
400
|
+
add_logging method_name, :define_singleton_method, options do |bind_object, args, &block|
|
401
|
+
m.call(*args, &block)
|
196
402
|
end
|
197
|
-
result
|
198
403
|
end
|
199
404
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
405
|
+
def add_instance_logging method_name, options
|
406
|
+
return unless method_defined? method_name
|
407
|
+
m = instance_method(method_name)
|
408
|
+
add_logging method_name, :define_method, options do |bind_object, args, &block|
|
409
|
+
m.bind(bind_object).(*args, &block)
|
205
410
|
end
|
206
411
|
end
|
207
|
-
|
208
|
-
def
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
412
|
+
|
413
|
+
def add_logging method_name, define_method, options, &bind_block
|
414
|
+
send(define_method, method_name) do |*args, &block|
|
415
|
+
log_args = {}
|
416
|
+
options.each do |key,value|
|
417
|
+
log_args[key] = case value
|
418
|
+
when Integer then args[value-1]
|
419
|
+
when Range then args[value]
|
420
|
+
when Symbol then eval(value.to_s)
|
421
|
+
when Proc then value.call(self)
|
422
|
+
else value
|
423
|
+
end
|
424
|
+
end
|
425
|
+
Wagn::Log::Performance.with_timer(method_name, log_args) do
|
426
|
+
bind_block.call(self, args, &block)
|
215
427
|
end
|
216
|
-
|
217
|
-
@@log << Wagn::Log::Performance::Entry.new(parent, level, args )
|
218
|
-
@@current_level += 1
|
219
|
-
@@active_entries << @@log.last
|
220
|
-
|
221
|
-
@@log.last
|
222
|
-
end
|
223
|
-
|
224
|
-
def finish_entry entry
|
225
|
-
min_time = Wagn.config.performance_logger[:min_time]
|
226
|
-
max_depth = Wagn.config.performance_logger[:max_depth]
|
227
|
-
if (max_depth && entry.level > max_depth) || (min_time && entry.duration < min_time)
|
228
|
-
entry.delete
|
229
428
|
end
|
230
|
-
@@active_entries.pop
|
231
|
-
@@current_level -= 1
|
232
429
|
end
|
233
|
-
|
430
|
+
|
431
|
+
def log_options_variable_name method_name, define_method
|
432
|
+
"@_#{self.class.name}_#{method_name.hash.to_s.sub(/^-/,'_')}_#{define_method}_logging_options".to_sym
|
433
|
+
end
|
434
|
+
|
234
435
|
end
|
436
|
+
|
437
|
+
|
235
438
|
end
|
236
439
|
|
237
440
|
end
|