wagn 1.14.6 → 1.14.7

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