wagn 1.14.6 → 1.14.7

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/app/controllers/card_controller.rb +15 -25
  4. data/lib/card/format.rb +30 -20
  5. data/lib/card/generators/set/USAGE +10 -3
  6. data/lib/card/generators/set/set_generator.rb +14 -6
  7. data/lib/card/generators/set/templates/set_spec_template.erb +1 -1
  8. data/lib/card/set.rb +3 -2
  9. data/lib/wagn.rb +7 -8
  10. data/lib/wagn/config/environments/development.rb +8 -0
  11. data/lib/wagn/generators/wagn/templates/Gemfile +1 -0
  12. data/lib/wagn/log.rb +224 -55
  13. data/mod/01_core/set/all/collection.rb +1 -1
  14. data/mod/01_core/set/all/fetch.rb +1 -1
  15. data/mod/01_core/set/all/notify.rb +3 -3
  16. data/mod/01_core/spec/format/html_format_spec.rb +0 -25
  17. data/mod/{05_standard → 02_basic_types}/format/css_format.rb +0 -0
  18. data/mod/{05_standard → 02_basic_types}/format/csv_format.rb +0 -0
  19. data/mod/{05_standard → 02_basic_types}/format/file_format.rb +0 -0
  20. data/mod/{05_standard → 02_basic_types}/format/js_format.rb +0 -0
  21. data/mod/{05_standard → 02_basic_types}/format/json_format.rb +0 -0
  22. data/mod/{05_standard → 02_basic_types}/format/rss_format.rb +0 -0
  23. data/mod/{05_standard → 02_basic_types}/format/xml_format.rb +0 -0
  24. data/mod/{05_standard → 02_basic_types}/set/all/all_css.rb +0 -0
  25. data/mod/{05_standard → 02_basic_types}/set/all/all_csv.rb +0 -0
  26. data/mod/{05_standard → 02_basic_types}/set/all/all_js.rb +0 -0
  27. data/mod/{05_standard → 02_basic_types}/set/all/base.rb +26 -20
  28. data/mod/{05_standard → 02_basic_types}/set/all/file.rb +0 -0
  29. data/mod/{05_standard → 02_basic_types}/set/all/json.rb +0 -0
  30. data/mod/{05_standard → 02_basic_types}/set/all/rss.rb +0 -0
  31. data/mod/{05_standard → 02_basic_types}/set/all/text.rb +0 -0
  32. data/mod/02_basic_types/set/type/pointer.rb +0 -1
  33. data/mod/{05_standard → 02_basic_types}/spec/set/all/all_css_spec.rb +0 -0
  34. data/mod/{05_standard → 02_basic_types}/spec/set/all/all_csv_spec.rb +0 -0
  35. data/mod/{05_standard → 02_basic_types}/spec/set/all/base_spec.rb +0 -0
  36. data/mod/{05_standard → 02_basic_types}/spec/set/all/file_spec.rb +0 -0
  37. data/mod/{05_standard → 02_basic_types}/spec/set/all/json_spec.rb +0 -0
  38. data/mod/{05_standard → 02_basic_types}/spec/set/all/rss_spec.rb +0 -0
  39. data/mod/{05_standard → 02_basic_types}/spec/set/all/text_spec.rb +0 -0
  40. data/mod/02_basic_types/spec/set/{plain_text_spec.rb → type/plain_text_spec.rb} +0 -0
  41. data/mod/02_basic_types/spec/set/{pointer_spec.rb → type/pointer_spec.rb} +0 -0
  42. data/mod/03_machines/lib/javascript/jquery-ui.js +11264 -12933
  43. data/mod/03_machines/lib/stylesheets/jquery-ui-smoothness.css +1 -1
  44. data/mod/03_machines/set/self/script_jquery_helper.rb +2 -1
  45. data/mod/05_standard/set/all/account.rb +1 -1
  46. data/mod/05_standard/set/all/error.rb +11 -4
  47. data/mod/05_standard/set/all/{rich_html.rb → rich_html/content.rb} +0 -0
  48. data/mod/05_standard/set/all/{editing.rb → rich_html/editing.rb} +0 -0
  49. data/mod/05_standard/set/all/{form.rb → rich_html/form.rb} +0 -0
  50. data/mod/05_standard/set/all/{header.rb → rich_html/header.rb} +4 -6
  51. data/mod/05_standard/set/all/{wrapper.rb → rich_html/wrapper.rb} +0 -0
  52. data/mod/05_standard/spec/set/all/error_spec.rb +7 -0
  53. data/mod/05_standard/spec/set/all/{rich_html_spec.rb → rich_html/form_spec.rb} +2 -10
  54. data/mod/05_standard/spec/set/all/rich_html/wrapper_spec.rb +26 -0
  55. data/spec/lib/wagn/log_spec.rb +101 -0
  56. metadata +36 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 10504368aca16ec7391adb5e9777576dec0d7ffe
4
- data.tar.gz: 6e82c4b52133d3c8341cb993d321ecbef2dadd01
3
+ metadata.gz: 3184f07aaf8e3892565b0a4975933d614c541e20
4
+ data.tar.gz: 2bc8a005bdec8efdf7bbdeb8f993ca83e0274445
5
5
  SHA512:
6
- metadata.gz: 7fde2052c74abcbb39c23ce8cf8eabfe1a585a5106ab0d478aab32a0ce92699a7041f97e37ff99e476e048731fd30037b8838ee40d7f4651458abd4de1109d6a
7
- data.tar.gz: deafe3aeb7de4766adcf4c9e13485db15d973a1666e81b3b6f96fb81619553165b931193b2cfc006bb9f234f9641456987f7e3625d4a89051d280ed2e253761d
6
+ metadata.gz: aae7e080cf2d3671947ca0e2dc5fcb6ccd2fc2946618aa3285b1cdc6469d1491ae69cc968701a8b45395c442f11f9d01d8a372b13d1952220541e49f08d7a4d1
7
+ data.tar.gz: 6c5e63fb992a4f4b2b15c691f2c65bc279d92032e257d4962a676d5fd07d0dfbacba8d2c7d5db6980b56d5d14d9ace5448e9ecdc1f4aa6bf8e40a4db9e08b078
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.14.6
1
+ 1.14.7
@@ -10,15 +10,17 @@ class CardController < ActionController::Base
10
10
  include Card::HtmlFormat::Location
11
11
  include Recaptcha::Verify
12
12
 
13
+ before_filter :start_performance_logger if Wagn.config.performance_logger
14
+ after_filter :stop_performance_logger if Wagn.config.performance_logger
15
+ after_filter :request_logger if Wagn.config.request_logger
16
+
13
17
  before_filter :per_request_setup, :except => [:asset]
14
18
  before_filter :load_id, :only => [ :read ]
15
19
  before_filter :load_card, :except => [:asset]
16
20
  before_filter :refresh_card, :only=> [ :create, :update, :delete, :rollback ]
17
21
 
18
- if Wagn.config.request_logger
19
- require 'csv'
20
- after_filter :request_logger
21
- end
22
+
23
+
22
24
 
23
25
  layout nil
24
26
 
@@ -126,27 +128,15 @@ class CardController < ActionController::Base
126
128
  end
127
129
 
128
130
  def request_logger
129
- unless env["REQUEST_URI"] =~ %r{^/files?/}
130
- log = []
131
- log << (Card::Env.ajax? ? "YES" : "NO")
132
- log << env["REMOTE_ADDR"]
133
- log << Card::Auth.current_id
134
- log << card.name
135
- log << action_name
136
- log << params['view'] || (s = params['success'] and s['view'])
137
- log << env["REQUEST_METHOD"]
138
- log << status
139
- log << env["REQUEST_URI"]
140
- log << DateTime.now.to_s
141
- log << env['HTTP_ACCEPT_LANGUAGE'].to_s.scan(/^[a-z]{2}/).first
142
- log << env["HTTP_REFERER"]
143
-
144
- log_dir = (Wagn.paths['request_log'] || Wagn.paths['log']).first
145
- log_filename = "#{Date.today}_#{Rails.env}.csv"
146
- File.open(File.join(log_dir,log_filename), "a") do |f|
147
- f.write CSV.generate_line(log)
148
- end
149
- end
131
+ Wagn::Log::Request.write_log_entry self
132
+ end
133
+
134
+ def start_performance_logger
135
+ Wagn::Log::Performance.start :method=>env["REQUEST_METHOD"], :message=>env["PATH_INFO"]
136
+ end
137
+
138
+ def stop_performance_logger
139
+ Wagn::Log::Performance.stop
150
140
  end
151
141
 
152
142
  protected
@@ -8,7 +8,7 @@ class Card
8
8
  :layout=>:layout, :new=>:edit, :setup=>:edit, :normal=>:normal, :template=>:template } #should be set in views
9
9
 
10
10
  cattr_accessor :ajax_call, :registered, :max_depth
11
- [ :perms, :denial_views, :error_codes, :view_tags, :aliases ].each do |acc|
11
+ [ :perms, :denial_views, :closed_views, :error_codes, :view_tags, :aliases ].each do |acc|
12
12
  cattr_accessor acc
13
13
  self.send "#{acc}=", {}
14
14
  end
@@ -34,9 +34,10 @@ class Card
34
34
 
35
35
  def extract_class_vars view, opts
36
36
  return unless opts.present?
37
- perms[view] = opts.delete(:perms) if opts[:perms]
38
- error_codes[view] = opts.delete(:error_code) if opts[:error_code]
39
- denial_views[view]= opts.delete(:denial) if opts[:denial]
37
+ perms[view] = opts.delete(:perms) if opts[:perms]
38
+ error_codes[view] = opts.delete(:error_code) if opts[:error_code]
39
+ denial_views[view] = opts.delete(:denial) if opts[:denial]
40
+ closed_views[view] = opts.delete(:closed) if opts[:closed]
40
41
 
41
42
  if tags = opts.delete(:tags)
42
43
  Array.wrap(tags).each do |tag|
@@ -182,7 +183,7 @@ class Card
182
183
  @current_view = view = ok_view canonicalize_view( view ), args
183
184
  args = default_render_args view, args
184
185
  with_inclusion_mode view do
185
- Wagn.with_logging card.name, :view, view, args do
186
+ Wagn.with_logging :view, view, :context=>card.name, :details=>args do
186
187
  send "_view_#{ view }", args
187
188
  end
188
189
  end
@@ -295,11 +296,16 @@ class Card
295
296
  def ok_view view, args={}
296
297
  return view if args.delete :skip_permissions
297
298
  approved_view = case
298
- when @depth >= @@max_depth ; :too_deep # prevent recursion. @depth tracks subformats
299
- when @@perms[view] == :none ; view # view requires no permissions
300
- when !card.known? &&
301
- !tagged( view, :unknown_ok ) ; view_for_unknown view, args # handle unknown cards (where view not exempt)
302
- else ; permitted_view view, args # run explicit permission checks
299
+ when @depth >= @@max_depth # prevent recursion. @depth tracks subformats
300
+ :too_deep
301
+ when @@perms[view] == :none # permission skipping specified in view definition
302
+ view
303
+ when args.delete(:skip_permissions) # permission skipping specified in args
304
+ view
305
+ when !card.known? && !tagged(view, :unknown_ok) # handle unknown cards (where view not exempt)
306
+ view_for_unknown view, args
307
+ else # run explicit permission checks
308
+ permitted_view view, args
303
309
  end
304
310
 
305
311
  args[:denied_view] = view if approved_view != view
@@ -422,17 +428,21 @@ class Card
422
428
  opts[:home_view] = [:closed, :edit].member?(view) ? :open : view
423
429
  # FIXME: special views should be represented in view definitions
424
430
 
425
- view = case
426
- when @mode == :edit
427
- if @@perms[view]==:none || nested_card.structure || nested_card.key.blank? # eg {{_self|type}} on new cards
428
- :blank
429
- else
430
- :edit_in_form
431
+ view = case @mode
432
+ when :edit
433
+ not_ready_for_form = @@perms[view]==:none || nested_card.structure || nested_card.key.blank? # eg {{_self|type}} on new cards
434
+ not_ready_for_form ? :blank : :edit_in_form
435
+ when :template
436
+ :template_rule
437
+ when :closed
438
+ case
439
+ when @@closed_views[view] == true || @@error_codes[view] ; view
440
+ when specified_view = @@closed_views[view] ; specified_view
441
+ when !nested_card.known? ; :closed_missing
442
+ else ; :closed_content
431
443
  end
432
- when @mode == :template ; :template_rule
433
- when @@perms[view]==:none ; view
434
- when @mode == :closed ; !nested_card.known? ? :closed_missing : :closed_content
435
- else ; view
444
+ else
445
+ view
436
446
  end
437
447
  sub.render view, opts
438
448
  #end
@@ -1,9 +1,16 @@
1
1
  Description:
2
2
  Generates new set files in mods and matching specs.
3
3
 
4
- Example:
4
+ Examples:
5
5
  wagn generate set standard type tshirt
6
6
 
7
7
  This will create:
8
- mods/05_standard/sets/type/tshirt.rb
9
- spec/mods/05_standard/sets/type/tshirt_spec.rb
8
+ mods/standard/sets/type/tshirt.rb
9
+ mods/standard/spec/sets/type/tshirt_spec.rb
10
+
11
+
12
+ wagn generate set standard type_plus_right basic about tshirt
13
+
14
+ This will create:
15
+ mods/standard/sets/type_plus_right/basic/about/tshirt.rb
16
+ mods/standard/spec/sets/type_plus_right/basic/about/tshirt_spec.rb
@@ -1,14 +1,22 @@
1
1
  class SetGenerator < Rails::Generators::Base
2
2
  source_root File.expand_path('../templates', __FILE__)
3
3
 
4
- argument :mod#, :required => true, :type => :array, :desc => "The names of the attachment(s) to add.",
5
- #:banner => "attachment_one attachment_two attachment_three ..."
6
- argument :set_pattern
7
- argument :anchor
4
+ argument :mod, :required => true
5
+ argument :set_pattern, :required => true
6
+ argument :anchors, :required=>true, :type=>:array
7
+ class_option :core, :type=>:boolean, :desc=>'create set files in Wagn gem'
8
+
8
9
 
9
10
  def create_files
10
- template 'set_template.erb', "mod/#{mod}/set/#{set_pattern}/#{anchor}.rb"
11
- template 'set_spec_template.erb', "spec/mod/#{mod}/set/#{set_pattern}/#{anchor}_spec.rb"
11
+ mod_path = if options.core?
12
+ File.join Wagn.gem_root, 'mod', mod
13
+ else
14
+ File.join 'mod', mod
15
+ end
16
+ set_path = File.join(mod_path, 'set', set_pattern, anchors[0..-2], "#{anchors.last}.rb")
17
+ spec_path = File.join(mod_path, 'spec', 'set', set_pattern, anchors[0..-2], "#{anchors.last}_spec.rb" )
18
+ template 'set_template.erb', set_path
19
+ template 'set_spec_template.erb', spec_path
12
20
  end
13
21
 
14
22
  end
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- describe Card::Set::<%= set_pattern.camelize %>::<%= anchor.camelize %> do
3
+ describe Card::Set::<%= set_pattern.camelize %>::<%= anchors.map(&:camelize).join('::') %> do
4
4
 
5
5
  end
@@ -55,7 +55,8 @@ class Card
55
55
  is running `wagn generate set modname set_pattern set_anchor`. In the current example, this
56
56
  would translate to `wagn generate set mymod right address`. Note that both the set_pattern
57
57
  and the set_anchor must correspond to the codename of a card in the database to function
58
- correctly.
58
+ correctly but you can add arbitrary subdirectories to organize your code rules. The rule above
59
+ for example could be saved in mywagn/mod/mymod/set/right/address/america/north/canada.rb.
59
60
 
60
61
 
61
62
  When Wagn loads, it uses these files to autogenerate a tmp_file that uses this set file to
@@ -135,7 +136,7 @@ class Card
135
136
 
136
137
  define_method event do
137
138
  run_callbacks event do
138
- Wagn.with_logging self.name, :event, event, opts do
139
+ Wagn.with_logging :event, event, :context=>self.name, :details=>opts do
139
140
  send final_method
140
141
  end
141
142
  end
@@ -24,22 +24,21 @@ module Wagn
24
24
  WAGN_GEM_ROOT
25
25
  end
26
26
 
27
- def with_logging cardname, method, message, details, &block
28
- if Wagn.config.performance_logger and
29
- Wagn.config.performance_logger[:methods] and
30
- Wagn.config.performance_logger[:methods].include? method
31
- Wagn::Log.start_block :cardname=>cardname, :method=>method, :message=>message, :details=>details
32
- result = block.call
33
- Wagn::Log.finish_block
34
- result
27
+ def with_logging method, message, opts, &block
28
+ if (pl_config=Wagn.config.performance_logger) && pl_config[:methods] && pl_config[:methods].include?(method)
29
+ Wagn::Log::Performance.with_timer(method, message, opts) do
30
+ block.call
31
+ end
35
32
  else
36
33
  block.call
37
34
  end
38
35
  end
39
36
 
37
+
40
38
  def future_stamp
41
39
  ## used in test data
42
40
  @@future_stamp ||= Time.local 2020,1,1,0,0,0
43
41
  end
44
42
  end
43
+
45
44
  end
@@ -33,6 +33,14 @@ Wagn.application.class.configure do
33
33
  # See everything in the log (default is :info)
34
34
  config.log_level = :debug
35
35
 
36
+ #change log_level to :wagn to activate performance logger
37
+ # config.performance_logger = {
38
+ # :methods => [:event, :search, :fetch, :view], # choose methods to log
39
+ # :min_time => 100, # show only method calls that are slower than 100ms
40
+ # :max_depth => 3, # show nested method calls only up to depth 3
41
+ # :details=> true # show method arguments and sql
42
+ # }
43
+
36
44
  # Only use best-standards-support built into browsers
37
45
  config.action_dispatch.best_standards_support = :builtin
38
46
 
@@ -103,6 +103,7 @@ group :development, :test do
103
103
  gem 'jasmine'
104
104
  gem 'jasmine-rails', :git=>"https://github.com/chuenlok/jasmine-rails.git"
105
105
  gem 'jasmine-jquery-rails'
106
+ gem 'phantomjs', '1.9.7.1' #locked because 1.9.8.0 is breaking
106
107
  end
107
108
 
108
109
  group :debug do
@@ -1,69 +1,238 @@
1
+ require 'csv'
1
2
 
2
- class Wagn::Log
3
- TAB_SIZE = 2
4
- @@log = []
5
- @@last_toplevel_card = nil
6
-
7
- class << self
8
-
9
- # args:
10
- # :method => :view|:event|:fetch|:search
11
- # :cardname, :message, :details
12
- def start_block args
13
- level = @@log.last ? @@log.last[:level] + 1 : 1
14
- @@log << args.merge( :start => Time.now, :level=>level, :subtree =>[] )
3
+ class Wagn::Log
4
+
5
+ class Request
6
+ def self.path
7
+ path = (Wagn.paths['request_log'] && Wagn.paths['request_log'].first) || File.dirname(Wagn.paths['log'].first)
8
+ filename = "#{Date.today}_#{Rails.env}.csv"
9
+ File.join path, filename
15
10
  end
16
11
 
17
- def finish_block
18
- log = @@log.pop
19
- duration = (Time.now - log[:start]) * 1000
20
- return if limit = Wagn.config.performance_logger[:limit] and limit > 0 and duration < limit
21
-
22
- log_msg = "#{ indent log[:level] }(%d.2ms) #{ log[:method] }: #{ log[:message] }" % duration
23
- log_msg += details log if Wagn.config.performance_logger[:details]
24
- log_msg += subtree log
25
-
26
- if log_parent = @@log.last
27
- if sibling = log_parent[:subtree].last and ( sibling[:card] == log[:cardname] or not log[:cardname] )
28
- sibling[:lines] << log_msg
29
- else
30
- log_parent[:subtree] << {:card=>log[:cardname], :lines=>[log_msg]}
31
- end
32
- else
33
- if log[:cardname] and @@last_toplevel_card != log[:cardname]
34
- @@last_toplevel_card = log[:cardname]
35
- Rails.logger.wagn log[:cardname]
12
+ def self.write_log_entry controller
13
+ return if controller.env["REQUEST_URI"] =~ %r{^/files?/}
14
+
15
+ controller.instance_eval do
16
+ log = []
17
+ log << (Card::Env.ajax? ? "YES" : "NO")
18
+ log << env["REMOTE_ADDR"]
19
+ log << Card::Auth.current_id
20
+ log << card.name
21
+ log << action_name
22
+ log << params['view'] || (s = params['success'] and s['view'])
23
+ log << env["REQUEST_METHOD"]
24
+ log << status
25
+ log << env["REQUEST_URI"]
26
+ log << DateTime.now.to_s
27
+ log << env['HTTP_ACCEPT_LANGUAGE'].to_s.scan(/^[a-z]{2}/).first
28
+ log << env["HTTP_REFERER"]
29
+
30
+ File.open(Wagn::Log::Request.path, "a") do |f|
31
+ f.write CSV.generate_line(log)
36
32
  end
37
- Rails.logger.wagn log_msg
38
33
  end
39
34
  end
40
-
41
-
42
- def indent level, args={}
43
- res = (' '*TAB_SIZE + '|') * level
44
- res += args[:no_link] ? ' ' : '--'
35
+
36
+ end
37
+
38
+
39
+ class Performance
40
+ TAB_SIZE = 3
41
+ @@log = []
42
+ @@context_entries = []
43
+ @@active_entries = []
44
+ @@current_level = 0
45
+
46
+ def self.the_log
47
+ @@the_log
45
48
  end
46
-
47
- def details log
48
- if log[:details]
49
- ", " + log[:details].to_s.gsub( "\n", "\n#{ indent( log[:level]+1, :no_link=>true) }" )
50
- else
51
- ''
49
+ class Entry
50
+ attr_accessor :level, :valid, :context, :parent, :children_cnt, :duration
51
+
52
+ def initialize( parent, level, args )
53
+ @start = Time.new
54
+ @message = "#{ args[:method] }: #{ args[:message] }"
55
+ @details = args[:details]
56
+ @context = args[:context]
57
+ @level = level
58
+ @duration = nil
59
+ @valid = true
60
+ @parent = parent
61
+ @children_cnt = 0
62
+ if @parent
63
+ @parent.add_children
64
+ #@sibling_nr = @parent.children_cnt
65
+ end
52
66
  end
67
+
68
+ def add_children
69
+ @children_cnt += 1
70
+ end
71
+
72
+ def delete_children
73
+ @children_cnt -= 1
74
+ end
75
+
76
+ def has_younger_siblings?
77
+ @parent && @parent.children_cnt > 0 #@sibling_nr
78
+ end
79
+
80
+ def save_duration
81
+ @duration = (Time.now - @start) * 1000
82
+ end
83
+
84
+ def delete
85
+ @valid = false
86
+ @parent.delete_children if @parent
87
+ end
88
+
89
+
90
+ # deletes the children counts in order to print the tree;
91
+ # must be called in the right order
92
+ #
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
95
+ # min_time or max_depth restrictions in the config, so we have to save all children relations for that
96
+ def to_s!
97
+ @to_s ||= begin
98
+ msg = indent
99
+ msg += if @duration
100
+ "(%d.2ms) #{@message}" % @duration
101
+ else
102
+ @message
103
+ end
104
+ if @details
105
+ msg += ", " + @details.to_s.gsub( "\n", "\n#{ indent(false) }#{' '* TAB_SIZE}" )
106
+ end
107
+ @parent.delete_children if @parent
108
+ msg
109
+ end
110
+ end
111
+
112
+ private
113
+
114
+ def indent link=true
115
+ @indent ||= begin
116
+ if @level == 0
117
+ "\n"
118
+ else
119
+ res = ' '
120
+ res += (1..level-1).inject('') do |msg, index|
121
+ if younger_siblings[index]
122
+ msg << '|' + ' ' * (TAB_SIZE-1)
123
+ else
124
+ msg << ' ' * TAB_SIZE
125
+ end
126
+ end
127
+
128
+ res += link ? '|--' : ' '
129
+ end
130
+ end
131
+ end
132
+
133
+ def younger_siblings
134
+ res = []
135
+ next_parent = self
136
+ while (next_parent)
137
+ res << next_parent.has_younger_siblings?
138
+ next_parent = next_parent.parent
139
+ end
140
+ res.reverse
141
+ end
142
+
53
143
  end
54
-
55
- def subtree log
56
- if log[:subtree].present?
57
- "\n" + log[:subtree].map do |subentry|
58
- msg = subentry[:card] ? "#{ indent(log[:level]) }#{ subentry[:card] }\n" : ''
59
- msg += subentry[:lines].join("\n")
60
- end.join("\n")
61
- else
62
- ''
144
+
145
+
146
+ class << self
147
+ def start args={}
148
+ @@current_level = 0
149
+ @@log = []
150
+ @@context_entries = []
151
+ @@active_entries = []
152
+ @@first_entry = new_entry(args)
63
153
  end
154
+
155
+ def stop
156
+ while (entry = @@context_entries.pop) do
157
+ finish_entry entry
158
+ end
159
+ if @@first_entry
160
+ @@first_entry.save_duration
161
+ finish_entry @@first_entry
162
+ end
163
+ print_log
164
+ end
165
+
166
+ def with_timer method, message, args, &block
167
+ if args[:context]
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
180
+ end
181
+
182
+ timer = new_entry args.merge(:method=>method, :message=>message)
183
+ begin
184
+ result = block.call
185
+ ensure
186
+ timer.save_duration
187
+ finish_entry timer
188
+
189
+ # finish all deeper nested contexts
190
+ while @@context_entries.last && @@context_entries.last.level >= @@current_level
191
+ finish_entry @@context_entries.pop
192
+ end
193
+ # we don't know whether the next entry will belong to the same context or will start a new one
194
+ # so we save the time
195
+ @@context_entries.last.save_duration if @@context_entries.last
196
+ end
197
+ result
198
+ end
199
+
200
+ private
201
+
202
+ def print_log
203
+ @@log.each do |entry|
204
+ Rails.logger.wagn entry.to_s! if entry.valid
205
+ end
206
+ end
207
+
208
+ def new_entry args
209
+ args.delete(:details) unless Wagn.config.performance_logger[:details]
210
+ level = @@current_level
211
+
212
+ last_entry = @@active_entries.last
213
+ parent = if last_entry
214
+ last_entry.level == level ? last_entry.parent : last_entry
215
+ 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
+ end
230
+ @@active_entries.pop
231
+ @@current_level -= 1
232
+ end
233
+
64
234
  end
65
-
66
235
  end
67
-
236
+
68
237
  end
69
238