trace-util-adv 0.1.1 → 0.2.0

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 (44) hide show
  1. data/CHANGELOG +7 -0
  2. data/VERSION +1 -1
  3. data/lib/README +87 -0
  4. data/lib/TODO.txt +12 -0
  5. data/lib/action_handler.rb +99 -0
  6. data/lib/appenders/appender.rb +97 -0
  7. data/lib/appenders/appender_registration.rb +16 -0
  8. data/lib/appenders/base_appender.rb +82 -0
  9. data/lib/appenders/file_appender.rb +72 -0
  10. data/lib/appenders/html_appender.rb +94 -0
  11. data/lib/appenders/logger_appender.rb +84 -0
  12. data/lib/appenders/stream_appender.rb +37 -0
  13. data/lib/appenders/template_log_appender.rb +28 -0
  14. data/lib/appenders/xml_appender.rb +75 -0
  15. data/lib/core_extensions.rb +101 -0
  16. data/lib/filters/base_filters.rb +178 -0
  17. data/lib/filters/composite_filters.rb +71 -0
  18. data/lib/filters/filter_factory.rb +17 -0
  19. data/lib/filters/message_filters.rb +35 -0
  20. data/lib/filters/tracing_filter.rb +88 -0
  21. data/lib/output_templates.rb +5 -0
  22. data/lib/rule_match.rb +38 -0
  23. data/lib/sample_filters.rb +95 -0
  24. data/lib/templates/base_template.rb +21 -0
  25. data/lib/templates/html_template.rb +48 -0
  26. data/lib/templates/string_template.rb +30 -0
  27. data/lib/templates/trace_output_handler.rb +47 -0
  28. data/lib/templates/xml_template.rb +36 -0
  29. data/lib/test_action_handler.rb +34 -0
  30. data/lib/test_appender.rb +29 -0
  31. data/lib/test_file_appender.rb +32 -0
  32. data/lib/test_filters.rb +112 -0
  33. data/lib/test_filters_chain.rb +100 -0
  34. data/lib/test_filters_create.rb +28 -0
  35. data/lib/test_html_appender.rb +66 -0
  36. data/lib/test_special_filters.rb +78 -0
  37. data/lib/test_xml_appender.rb +66 -0
  38. data/lib/test_xml_gen.rb +46 -0
  39. data/lib/trace_appenders.rb +9 -0
  40. data/lib/trace_calls.rb +86 -0
  41. data/lib/trace_ext.rb +57 -0
  42. data/lib/trace_filters.rb +4 -0
  43. data/trace-util-adv.gemspec +98 -0
  44. metadata +44 -2
@@ -0,0 +1,94 @@
1
+ # surround html ouput with wrapper-html
2
+ # include jquery and css
3
+ # collapse non-important regions and expand important ones
4
+
5
+ # TODO: how to ensure html ouput finishes
6
+ # file.seek(-20, IO:SEEK_END)
7
+ module Tracing
8
+ class HtmlAppender < FileAppender
9
+ attr_accessor :to_file, :html_output
10
+
11
+ class << self
12
+ def default_path
13
+ return if !@default_path
14
+ if !File.exists?(@default_path)
15
+ FileUtils.mkdir_p @default_path
16
+ end
17
+ @default_path
18
+ end
19
+
20
+ def default_path=(path)
21
+ @default_path = path
22
+ end
23
+ end
24
+
25
+ def initialize(init_options = nil)
26
+ @tracer = Tracing::OutputTemplate::HtmlTrace.new
27
+ super(init_options)
28
+ @html_output = html_begin
29
+
30
+ return if !init_options
31
+ # write to file
32
+ @to_file = init_options[:to_file]
33
+ if @to_file
34
+ write_wrap_file(to_file)
35
+ else
36
+ html_output << html_begin << html_end
37
+ end
38
+ end
39
+
40
+ def write_wrap_file(file)
41
+ file = file_path(file)
42
+ File.open(file, "w") do |file|
43
+ file.puts html_begin
44
+ file.puts html_end
45
+ end
46
+ end
47
+
48
+ def create_initial_file(file)
49
+ write_wrap_file(file)
50
+ end
51
+
52
+ def html_begin
53
+ %q{<?xml version="1.0" encoding="UTF-8"?>
54
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
55
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
56
+ <head>
57
+ <title>Tracing :: abc</title>
58
+ <link rel="stylesheet" href="tracing.css" type="text/css" media="screen" title="tracing" charset="utf-8">
59
+ <script type="text/javascript" src="jquery-1.3.2.min.js"></script>
60
+ <script type="text/javascript" src="tracing.js"></script>
61
+ </head>
62
+ <body>}
63
+ end
64
+
65
+ def html_end
66
+ %q{
67
+ </body>
68
+ </html>
69
+ }
70
+ end
71
+
72
+ # perform append
73
+ # perform append
74
+ def allow_append(txt, context)
75
+ # check if BEGIN or END
76
+ if txt.include?('BEGIN')
77
+ txt = tracer.handle_before_call(context)
78
+ elsif txt.include?('END')
79
+ txt = tracer.handle_after_call(context)
80
+ end
81
+
82
+ if to_file
83
+ insert_into_file(to_file, txt, html_end)
84
+ else
85
+ # insert into string
86
+ html_output = txt[0..-html_end.length] + txt + html_end
87
+ end
88
+ end
89
+
90
+ # silently ignore
91
+ def not_allow_append(lines, context)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,84 @@
1
+ require 'logger'
2
+
3
+ # append log to STDOUT Logger
4
+ module Tracing
5
+ class LoggerAppender < BaseAppender
6
+ attr_reader :logger
7
+
8
+ def stream(options)
9
+ if options
10
+ case options[:stream]
11
+ when :error
12
+ STDERR
13
+ else
14
+ STDOUT
15
+ end
16
+ else
17
+ STDOUT
18
+ end
19
+ end
20
+
21
+ def log_lv(options)
22
+ if options
23
+ case options[:log_level]
24
+ when :info
25
+ Logger::INFO
26
+ when :warning
27
+ Logger::WARNING
28
+ when :fatal
29
+ Logger::FATAL
30
+ else
31
+ Logger::DEBUG
32
+ end
33
+ else
34
+ Logger::DEBUG
35
+ end
36
+ end
37
+
38
+ def initialize(init_options)
39
+ @tracer = Tracing::OutputTemplate::StringTrace.new
40
+ super(init_options)
41
+
42
+ if init_options.kind_of? Hash
43
+ logger_options = init_options[:logger] if init_options
44
+ end
45
+ log_stream = stream(logger_options)
46
+ log_level = log_lv(logger_options)
47
+
48
+ @logger ||= Logger.new(log_stream)
49
+ @logger.level ||= log_level
50
+ end
51
+
52
+ def log_debug(txt)
53
+ logger.debug txt
54
+ end
55
+
56
+ def log_info(txt)
57
+ logger.info txt
58
+ end
59
+
60
+ # perform append
61
+ def allow_append(txt, context)
62
+ # check if BEGIN or END
63
+ if txt.include?('BEGIN')
64
+ txt = tracer.handle_before_call(context)
65
+ elsif txt.include?('END')
66
+ txt = tracer.handle_after_call(context)
67
+ end
68
+
69
+ if txt.include?('INFO')
70
+ log_info txt
71
+ elsif txt.include?('WARNING')
72
+ log_warning txt
73
+ elsif txt.include?('ERROR')
74
+ log_error txt
75
+ else
76
+ log_debug txt
77
+ end
78
+ end
79
+
80
+ # silently ignore
81
+ def not_allow_append(lines, context)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,37 @@
1
+ module Tracing
2
+ class StreamAppender < BaseAppender
3
+ attr_accessor :stream
4
+
5
+ def configure_stream(options)
6
+ @stream = $stdout
7
+ if options
8
+ case options[:stream]
9
+ when :error
10
+ @stream = $stderr
11
+ end
12
+ end
13
+ end
14
+
15
+ def initialize(init_options)
16
+ @tracer = Tracing::OutputTemplate::StringTrace.new
17
+ super(init_options)
18
+ configure_stream(init_options)
19
+ end
20
+
21
+ # perform append
22
+ def allow_append(txt, context)
23
+ # check if BEGIN or END
24
+ if txt.include?('BEGIN')
25
+ txt = tracer.handle_before_call(context)
26
+ elsif txt.include?('END')
27
+ txt = tracer.handle_after_call(context)
28
+ end
29
+
30
+ stream.puts txt
31
+ end
32
+
33
+ # silently ignore
34
+ def not_allow_append(lines, context)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ module Tracing
2
+ class TemplateLogAppender < FileAppender
3
+
4
+ def initialize(init_options)
5
+ @tracer = Tracing::OutputTemplate::StringTrace.new
6
+ super(init_options)
7
+ end
8
+
9
+ # get template path
10
+ def template_path(context)
11
+ obj = context[:self]
12
+ template_path = obj.instance_variable_get :@template_path
13
+ end
14
+
15
+ # perform append
16
+ def allow_append(lines, context)
17
+ path = template_path(context)
18
+ if path
19
+ log_file = + '.log'
20
+ write_file(log_file)
21
+ end
22
+ end
23
+
24
+ # silently ignore
25
+ def not_allow_append(lines, context)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,75 @@
1
+ # append log to xml-stream or file
2
+ module Tracing
3
+ class XmlAppender < FileAppender
4
+ attr_accessor :xml_output, :to_file
5
+
6
+ class << self
7
+ def default_path
8
+ return if !@default_path
9
+ if !File.exists?(@default_path)
10
+ FileUtils.mkdir_p @default_path
11
+ end
12
+ @default_path
13
+ end
14
+
15
+ def default_path=(path)
16
+ @default_path = path
17
+ end
18
+ end
19
+
20
+ def initialize(init_options)
21
+ @tracer = Tracing::OutputTemplate::XmlTrace.new
22
+ super(init_options)
23
+ @xml_output = xml_begin
24
+
25
+ return if !init_options
26
+ # write to file
27
+ @to_file = init_options[:to_file]
28
+ if @to_file
29
+ write_wrap_file(to_file)
30
+ else
31
+ xml_output << xml_begin << xml_end
32
+ end
33
+ end
34
+
35
+ def create_initial_file(file)
36
+ write_wrap_file(file)
37
+ end
38
+
39
+ def write_wrap_file(file)
40
+ File.open(file, "w") do |file|
41
+ file.puts xml_begin
42
+ file.puts xml_end
43
+ end
44
+ end
45
+
46
+ def xml_begin
47
+ "<?xml version='1.0' encoding='UTF-8'?>\n<tracing>\n"
48
+ end
49
+
50
+ def xml_end
51
+ "</tracing>"
52
+ end
53
+
54
+ # perform append
55
+ def allow_append(txt, context)
56
+ # check if BEGIN or END
57
+ if txt.include?('BEGIN')
58
+ txt = tracer.handle_before_call(context)
59
+ elsif txt.include?('END')
60
+ txt = tracer.handle_after_call(context)
61
+ end
62
+
63
+ if to_file
64
+ insert_into_file(to_file, txt, xml_end)
65
+ else
66
+ # insert into string
67
+ xml_output = xml_output[0..-xml_end.length] + txt + xml_end
68
+ end
69
+ end
70
+
71
+ # silently ignore
72
+ def not_allow_append(lines, context)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,101 @@
1
+ require 'rule_match'
2
+
3
+ class String
4
+ def modules
5
+ self.split("::")[0..-2]
6
+ end
7
+
8
+ def class_name
9
+ self.split("::")[-1..-1]
10
+ end
11
+
12
+ def in_module?(module_name)
13
+ modules = self.modules
14
+ modules.include?(module_name)
15
+ end
16
+
17
+ def split_names
18
+ self.split(/\s|,/)
19
+ end
20
+
21
+ end
22
+
23
+
24
+ class Array
25
+ include Tracing::RuleMatch
26
+
27
+ def add(obj)
28
+ self << obj
29
+ self.flatten!
30
+ end
31
+ end
32
+
33
+ class Symbol
34
+ def prefix(pre)
35
+ (pre.to_s + self.to_s).to_sym
36
+ end
37
+ end
38
+
39
+ class Hash
40
+ include Tracing::RuleMatch
41
+
42
+ def try_create_filter(symbol)
43
+ isymbol = has_i(symbol) || has_x(symbol)
44
+ # puts "try_create_filter: " + isymbol.inspect
45
+ if isymbol
46
+ filter_names = self[isymbol]
47
+ # puts "filter_names:" + filter_names.inspect
48
+ {symbol => {:include => filter_names}}
49
+ end
50
+ end
51
+
52
+ def rules_allow_action(name)
53
+ rule_allow_action(name)
54
+ end
55
+
56
+ def rule_list(rules)
57
+ if rules.kind_of? String
58
+ rules.split_names
59
+ else
60
+ rules
61
+ end
62
+ end
63
+
64
+ # return a symbol, either - :include, :exclude or :yield (let next filter decide)
65
+ def rule_allow_action(name)
66
+ include_rules = rule_list(self[:include])
67
+ if include_rules && include_rules.size > 0
68
+ # puts "Rule include"
69
+ res = include_rules.matches_any?(name)
70
+ return :include if res
71
+ end
72
+ exclude_rules = rule_list(self[:exclude])
73
+ if exclude_rules
74
+ # puts "Rule exclude"
75
+ return :exclude if exclude_rules.matches_any?(name)
76
+ end
77
+ # puts "Not included or excluded"
78
+ if !self[:default].nil?
79
+ # puts "Return default: #{self[:default]}"
80
+ return self[:default]
81
+ end
82
+ # puts "Rule yields"
83
+ return :yield
84
+ rescue RuleTypeError
85
+ # puts "error"
86
+ return :exclude
87
+ end
88
+
89
+ protected
90
+ def has_i(symbol)
91
+ isym = symbol.prefix('i')
92
+ self.has_key?(isym) ? isym : false
93
+ end
94
+
95
+ def has_x(symbol)
96
+ self.has_key?(symbol.prefix('i'))
97
+ end
98
+
99
+ end
100
+
101
+
@@ -0,0 +1,178 @@
1
+ module Tracing
2
+
3
+ # abstract filter
4
+ class BaseFilter
5
+ attr_reader :name
6
+ attr_accessor :rules
7
+
8
+ class << self
9
+ attr_accessor :filters
10
+
11
+ # register symbol => filter mappings
12
+ def register_filters(hash)
13
+ filters.merge!(hash)
14
+ end
15
+
16
+ # array of symbols
17
+ # [:special_filter, :stream_filter]
18
+ def unregister_filters(hash)
19
+ filters.reject!{|key, value| hash.include? key}
20
+ end
21
+
22
+ def filter_rule_mappings
23
+ {
24
+ :module_rules => :module_filter,
25
+ :class_rules => :class_filter,
26
+ :method_rules => :method_filter,
27
+ :var_rules => :vars_filter,
28
+ :modules => :composite_module_filter,
29
+ :classes => :composite_class_filter,
30
+ :vars => :composite_vars_filter
31
+ }
32
+ end
33
+
34
+ def convenience_map
35
+ {
36
+ :module => :module_filter,
37
+ :class => :class_filter,
38
+ :method => :method_filter,
39
+ :vars => :vars_filter,
40
+ }
41
+ end
42
+
43
+
44
+ def default_filters
45
+ {
46
+ :module_filter => Tracing::ModuleFilter,
47
+ :class_filter => Tracing::ClassFilter,
48
+ :method_filter => Tracing::MethodFilter,
49
+ :vars_filter => Tracing::InstanceVarFilter,
50
+ :composite_module_filter => Tracing::CompositeModuleFilter,
51
+ :composite_class_filter => Tracing::CompositeClassFilter,
52
+ :composite_vars_filter => Tracing::CompositeInstanceVarFilter
53
+ }
54
+ end
55
+
56
+ def get_filter(options)
57
+ convenience_map.select do |key, _filter|
58
+ return _filter if options.has_key?(key) || options.has_key?(_filter)
59
+ end
60
+ filter_rule_mappings.select do |key, _filter|
61
+ return _filter if options.has_key? key
62
+ end
63
+ return options
64
+ end
65
+
66
+ # Example:
67
+ # {:method, :include => 'hello,way'}
68
+ # {:class, :include => 'A,B', :exclude => 'C'}
69
+ def filter_by_hash(options)
70
+ filters ||= default_filters
71
+
72
+ # try by factory
73
+ new_filter = Tracing::Filter.create_filter(options)
74
+
75
+ # puts "New filter: #{new_filter.inspect}"
76
+
77
+ options = new_filter if new_filter
78
+
79
+ # try by other means
80
+ type = get_filter(options)
81
+
82
+ if type && type.kind_of?(Symbol)
83
+ filter_class = filters[type]
84
+
85
+ # puts "filter class: #{filter_class}"
86
+
87
+ # ensure options has rules
88
+ if filter_class
89
+ filter_class.new(options)
90
+ else
91
+ raise Exception, "Filterclass not found"
92
+ end
93
+ end
94
+ end
95
+
96
+ # TODO: Refactor using symbol map!
97
+ def create_filter(options)
98
+ if options.kind_of? Hash
99
+ _filter = filter_by_hash(options)
100
+ elsif options.kind_of? BaseFilter
101
+ options
102
+ else
103
+ nil
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ def initialize(options)
110
+ @name = options[:name] || "Unknown filter"
111
+ end
112
+
113
+ def name_allow_action(name)
114
+ res = rules.rules_allow_action(name)
115
+ end
116
+ end
117
+
118
+ # filter on module
119
+ class ModuleFilter < BaseFilter
120
+ def initialize(options)
121
+ super(options)
122
+ @rules = options[:module_rules] || {}
123
+ end
124
+
125
+ def allow_action(msg, context)
126
+ name = context[:full_module_name]
127
+ allow = name_allow_action(name)
128
+ end
129
+ end
130
+
131
+ # filter on class name
132
+ class ClassFilter < BaseFilter
133
+ def initialize(options)
134
+ super(options)
135
+ @rules = options[:class_rules] || {}
136
+ end
137
+
138
+ def allow_action(msg, context)
139
+ name = context[:class_name]
140
+ allow = name_allow_action(name)
141
+ end
142
+ end
143
+
144
+
145
+ # filter on method
146
+ class MethodFilter < BaseFilter
147
+ def initialize(options)
148
+ super(options)
149
+ @rules = options[:method_rules] || options[:method_filter] || {}
150
+ end
151
+
152
+ def allow_action(msg, context)
153
+ name = context[:method_name]
154
+ @encountered ||= []
155
+ name_allow_action(name)
156
+ end
157
+ end
158
+
159
+ # filter on instance variables
160
+ class InstanceVarFilter < BaseFilter
161
+ attr_accessor :var_name
162
+
163
+ def initialize(options)
164
+ super(options)
165
+ @rules = options[:var_rules] || {}
166
+ var_name = options[:var_name]
167
+ end
168
+
169
+ def allow_action(msg, context)
170
+ obj = context[:self]
171
+ if var_name.kind_of?(Symbol) || var_name.kind_of?(String)
172
+ value = obj.instance_variable_get(var_name)
173
+ return name_allow_action(value)
174
+ end
175
+ :yield
176
+ end
177
+ end
178
+ end