wagn 1.14.7 → 1.14.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|