trace_viz 0.0.2 → 1.0.1

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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +68 -43
  3. data/Steepfile +34 -0
  4. data/examples/eu_central_bank.rb +69 -0
  5. data/examples/example.cast +189 -285
  6. data/lib/trace_viz/adapters/base_adapter.rb +24 -1
  7. data/lib/trace_viz/adapters/trace_point_adapter.rb +3 -10
  8. data/lib/trace_viz/builders/base_builder.rb +11 -0
  9. data/lib/trace_viz/builders/diagram/base_builder.rb +10 -0
  10. data/lib/trace_viz/builders/diagram/message_builder.rb +96 -0
  11. data/lib/trace_viz/builders/diagram/sequence_builder.rb +50 -0
  12. data/lib/trace_viz/collectors/base_collector.rb +42 -35
  13. data/lib/trace_viz/collectors/filters/base_class_filter.rb +31 -0
  14. data/lib/trace_viz/collectors/filters/base_exclude_filter.rb +16 -0
  15. data/lib/trace_viz/collectors/filters/base_filter.rb +2 -8
  16. data/lib/trace_viz/collectors/filters/base_include_filter.rb +16 -0
  17. data/lib/trace_viz/collectors/filters/exclude_classes_filter.rb +4 -17
  18. data/lib/trace_viz/collectors/filters/exclude_default_classes_filter.rb +22 -26
  19. data/lib/trace_viz/collectors/filters/include_classes_filter.rb +4 -17
  20. data/lib/trace_viz/collectors/hierarchy_linker.rb +30 -0
  21. data/lib/trace_viz/collectors/matchers/base_matcher.rb +13 -0
  22. data/lib/trace_viz/collectors/matchers/trace_point_action_matcher.rb +12 -10
  23. data/lib/trace_viz/collectors/matchers/within_depth_matcher.rb +6 -5
  24. data/lib/trace_viz/collectors/steps/assign_depth_for_call_step.rb +30 -0
  25. data/lib/trace_viz/collectors/steps/assign_depth_for_return_step.rb +39 -0
  26. data/lib/trace_viz/collectors/steps/base_step.rb +27 -0
  27. data/lib/trace_viz/collectors/steps/build_hierarchy_step.rb +32 -0
  28. data/lib/trace_viz/collectors/{evaluators/hidden_evaluator.rb → steps/hidden_step.rb} +9 -5
  29. data/lib/trace_viz/collectors/steps/linking_step.rb +36 -0
  30. data/lib/trace_viz/collectors/{evaluators/filter_evaluator.rb → steps/validation_step.rb} +9 -6
  31. data/lib/trace_viz/collectors/steps.rb +10 -0
  32. data/lib/trace_viz/collectors/trace_pipeline.rb +26 -0
  33. data/lib/trace_viz/collectors/trace_pipeline_builder.rb +29 -0
  34. data/lib/trace_viz/collectors/trace_point_collector.rb +1 -11
  35. data/lib/trace_viz/config/validator.rb +6 -5
  36. data/lib/trace_viz/configuration.rb +3 -3
  37. data/lib/trace_viz/context/tracking_context.rb +4 -0
  38. data/lib/trace_viz/core/tracer.rb +2 -0
  39. data/lib/trace_viz/defaults/actions.rb +84 -0
  40. data/lib/trace_viz/defaults/colors.rb +61 -0
  41. data/lib/trace_viz/defaults/config.rb +91 -0
  42. data/lib/trace_viz/defaults/themes.rb +66 -0
  43. data/lib/trace_viz/defaults.rb +10 -129
  44. data/lib/trace_viz/exporters/base_exporter.rb +31 -13
  45. data/lib/trace_viz/exporters/export_manager.rb +33 -0
  46. data/lib/trace_viz/exporters/mermaid_exporter.rb +17 -0
  47. data/lib/trace_viz/exporters/registry.rb +27 -0
  48. data/lib/trace_viz/exporters/text_exporter.rb +2 -2
  49. data/lib/trace_viz/extractors/base_extractor.rb +17 -0
  50. data/lib/trace_viz/extractors/diagram/base_extractor.rb +18 -0
  51. data/lib/trace_viz/extractors/diagram/box_extractor.rb +50 -0
  52. data/lib/trace_viz/extractors/diagram/message_extractor.rb +23 -0
  53. data/lib/trace_viz/extractors/diagram/participant_extractor.rb +37 -0
  54. data/lib/trace_viz/extractors/diagram/processors/message_processor.rb +93 -0
  55. data/lib/trace_viz/formatters/base_formatter.rb +4 -30
  56. data/lib/trace_viz/formatters/base_formatter_factory.rb +23 -0
  57. data/lib/trace_viz/formatters/diagram/sequence/base_formatter.rb +14 -0
  58. data/lib/trace_viz/formatters/diagram/sequence/message_formatter.rb +37 -0
  59. data/lib/trace_viz/formatters/diagram_formatter.rb +10 -0
  60. data/lib/trace_viz/formatters/export/base_formatter.rb +12 -0
  61. data/lib/trace_viz/formatters/export/formatter_factory.rb +22 -0
  62. data/lib/trace_viz/formatters/export/method_call_formatter.rb +21 -0
  63. data/lib/trace_viz/formatters/export/method_return_formatter.rb +22 -0
  64. data/lib/trace_viz/formatters/export/summary_group_formatter.rb +35 -0
  65. data/lib/trace_viz/formatters/helpers/depth_helper.rb +2 -8
  66. data/lib/trace_viz/formatters/helpers/digram/action_helper.rb +17 -0
  67. data/lib/trace_viz/formatters/helpers/digram/result_helper.rb +39 -0
  68. data/lib/trace_viz/formatters/helpers/indent_helper.rb +1 -1
  69. data/lib/trace_viz/formatters/helpers/log/color_helper.rb +23 -0
  70. data/lib/trace_viz/formatters/helpers/log/depth_helper.rb +22 -0
  71. data/lib/trace_viz/formatters/helpers/log/method_name_helper.rb +29 -0
  72. data/lib/trace_viz/formatters/helpers/log/params_helper.rb +55 -0
  73. data/lib/trace_viz/formatters/helpers/log/result_helper.rb +27 -0
  74. data/lib/trace_viz/formatters/helpers/log/summary/params_helper.rb +57 -0
  75. data/lib/trace_viz/formatters/helpers/method_details_helper.rb +1 -1
  76. data/lib/trace_viz/formatters/helpers/params_helper.rb +30 -9
  77. data/lib/trace_viz/formatters/helpers/result_helper.rb +5 -4
  78. data/lib/trace_viz/formatters/helpers/source_helper.rb +6 -4
  79. data/lib/trace_viz/formatters/helpers/summary/params_helper.rb +45 -0
  80. data/lib/trace_viz/formatters/helpers/summary/source_helper.rb +24 -0
  81. data/lib/trace_viz/formatters/helpers/time_helper.rb +2 -2
  82. data/lib/trace_viz/formatters/helpers.rb +10 -0
  83. data/lib/trace_viz/formatters/log/base_formatter.rb +13 -0
  84. data/lib/trace_viz/formatters/log/formatter_factory.rb +22 -0
  85. data/lib/trace_viz/formatters/log/method_call_formatter.rb +34 -0
  86. data/lib/trace_viz/formatters/log/method_return_formatter.rb +24 -0
  87. data/lib/trace_viz/formatters/log/summary_group_formatter.rb +40 -0
  88. data/lib/trace_viz/formatters/log/verbose_formatter.rb +14 -0
  89. data/lib/trace_viz/formatters/trace_data_formatter.rb +24 -0
  90. data/lib/trace_viz/helpers/config_helper.rb +17 -0
  91. data/lib/trace_viz/helpers/trace_point/param_helper.rb +98 -0
  92. data/lib/trace_viz/helpers/tracking_helper.rb +26 -0
  93. data/lib/trace_viz/helpers.rb +9 -0
  94. data/lib/trace_viz/logger.rb +9 -20
  95. data/lib/trace_viz/loggers/base_logger.rb +29 -0
  96. data/lib/trace_viz/loggers/log_level_resolver.rb +18 -0
  97. data/lib/trace_viz/loggers/logging_manager.rb +46 -0
  98. data/lib/trace_viz/loggers/post_collection_logger.rb +44 -0
  99. data/lib/trace_viz/loggers/trace_logger.rb +14 -18
  100. data/lib/trace_viz/loggers/trace_stats_logger.rb +28 -14
  101. data/lib/trace_viz/managers/diagram/participant_manager.rb +23 -0
  102. data/lib/trace_viz/models/box.rb +19 -0
  103. data/lib/trace_viz/models/diagram.rb +27 -0
  104. data/lib/trace_viz/models/message.rb +16 -0
  105. data/lib/trace_viz/models/participant.rb +18 -0
  106. data/lib/trace_viz/models.rb +8 -0
  107. data/lib/trace_viz/renderers/base_renderer.rb +27 -0
  108. data/lib/trace_viz/renderers/diagram/sequence_renderer.rb +59 -0
  109. data/lib/trace_viz/renderers/render_context.rb +17 -0
  110. data/lib/trace_viz/renderers/renderer_builder.rb +20 -0
  111. data/lib/trace_viz/renderers/renderer_factory.rb +29 -0
  112. data/lib/trace_viz/renderers/summary_renderer.rb +34 -0
  113. data/lib/trace_viz/renderers/verbose_renderer.rb +29 -0
  114. data/lib/trace_viz/shared/renderer_helper.rb +25 -0
  115. data/lib/trace_viz/shared.rb +8 -0
  116. data/lib/trace_viz/syntax/mermaid/sequence_syntax.rb +99 -0
  117. data/lib/trace_viz/trace_data/base.rb +22 -22
  118. data/lib/trace_viz/trace_data/node.rb +39 -0
  119. data/lib/trace_viz/trace_data/root_node.rb +24 -0
  120. data/lib/trace_viz/trace_data/summary_node.rb +45 -0
  121. data/lib/trace_viz/trace_data/trace_point/base.rb +26 -31
  122. data/lib/trace_viz/trace_data/trace_point/method_call.rb +25 -16
  123. data/lib/trace_viz/trace_data/trace_point/method_return.rb +21 -1
  124. data/lib/trace_viz/traits/depth_trackable.rb +13 -0
  125. data/lib/trace_viz/traits/identifiable.rb +25 -0
  126. data/lib/trace_viz/traits/time_trackable.rb +13 -0
  127. data/lib/trace_viz/traits.rb +10 -0
  128. data/lib/trace_viz/transformers/base_transformer.rb +29 -0
  129. data/lib/trace_viz/transformers/summary_transformer.rb +70 -0
  130. data/lib/trace_viz/utils/alias_generator.rb +58 -0
  131. data/lib/trace_viz/utils/colorize.rb +6 -6
  132. data/lib/trace_viz/utils/format/key_value_formatter.rb +42 -0
  133. data/lib/trace_viz/utils/format/value_truncator.rb +123 -0
  134. data/lib/trace_viz/utils/id_generator.rb +35 -0
  135. data/lib/trace_viz/utils.rb +8 -0
  136. data/lib/trace_viz/version.rb +1 -1
  137. data/sig/adapters/base_adapter.rbs +11 -0
  138. data/sig/adapters/trace_point_adapter.rbs +13 -0
  139. data/sig/collectors/filters/registry.rbs +13 -0
  140. data/sig/collectors/trace_point_collector.rbs +17 -0
  141. data/sig/config/copier.rbs +15 -0
  142. data/sig/config/validator.rbs +18 -0
  143. data/sig/configuration.rbs +22 -0
  144. data/sig/context/base_context.rbs +9 -0
  145. data/sig/context/config_context.rbs +13 -0
  146. data/sig/context/manager.rbs +10 -0
  147. data/sig/context/map.rbs +13 -0
  148. data/sig/context.rbs +5 -0
  149. data/sig/core/tracer.rbs +7 -0
  150. data/sig/core.rbs +4 -0
  151. data/sig/defaults.rbs +17 -0
  152. data/sig/errors.rbs +13 -0
  153. data/sig/logger.rbs +33 -0
  154. data/sig/trace_viz.rbs +1 -2
  155. data/sig/utils/colorize.rbs +8 -0
  156. data/sig/utils/format_utils/key_value_formatter.rbs +16 -0
  157. data/sig/utils/format_utils/value_truncator.rbs +19 -0
  158. data/sig/utils/format_utils.rbs +8 -0
  159. data/sig/version.rbs +3 -0
  160. metadata +124 -18
  161. data/lib/trace_viz/collectors/depth_manager.rb +0 -37
  162. data/lib/trace_viz/collectors/evaluators/base_evaluator.rb +0 -23
  163. data/lib/trace_viz/exporters/formatters/base_formatter.rb +0 -12
  164. data/lib/trace_viz/exporters/formatters/method_call_formatter.rb +0 -21
  165. data/lib/trace_viz/exporters/formatters/method_return_formatter.rb +0 -22
  166. data/lib/trace_viz/exporters/transformers/base_transformer.rb +0 -25
  167. data/lib/trace_viz/exporters/transformers/text_transformer.rb +0 -28
  168. data/lib/trace_viz/loggers/trace_builder.rb +0 -30
  169. data/lib/trace_viz/loggers/trace_formatters/base_formatter.rb +0 -32
  170. data/lib/trace_viz/loggers/trace_formatters/method_call_formatter.rb +0 -21
  171. data/lib/trace_viz/loggers/trace_formatters/method_return_formatter.rb +0 -22
  172. data/lib/trace_viz/utils/format_utils.rb +0 -67
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Managers
5
+ module Diagram
6
+ class ParticipantsManager
7
+ def initialize(participants)
8
+ @participants_map = build_participants_map(participants)
9
+ end
10
+
11
+ def find(name)
12
+ @participants_map[name.to_s]
13
+ end
14
+
15
+ private
16
+
17
+ def build_participants_map(participants)
18
+ participants.each_with_object({}) { |participant, memo| memo[participant.name] = participant }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Models
5
+ class Box
6
+ attr_reader :participants, :color, :description
7
+
8
+ def initialize(color:, description:)
9
+ @color = color
10
+ @description = description
11
+ @participants = []
12
+ end
13
+
14
+ def add_participant(participant)
15
+ @participants << participant
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Models
5
+ class Diagram
6
+ attr_reader :boxes, :participants, :messages
7
+
8
+ def initialize
9
+ @boxes = []
10
+ @participants = []
11
+ @messages = []
12
+ end
13
+
14
+ def add_box(box)
15
+ @boxes << box unless @boxes.include?(box)
16
+ end
17
+
18
+ def add_participant(participant)
19
+ @participants << participant unless @participants.include?(participant)
20
+ end
21
+
22
+ def add_message(message)
23
+ @messages << message
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Models
5
+ class Message
6
+ attr_reader :type, :from, :to, :content
7
+
8
+ def initialize(type:, from:, to:, content:)
9
+ @type = type
10
+ @from = from
11
+ @to = to
12
+ @content = content
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Models
5
+ class Participant
6
+ attr_accessor :name, :alias_name
7
+
8
+ def initialize(name:, alias_name: nil)
9
+ @name = name
10
+ @alias_name = alias_name
11
+ end
12
+
13
+ def ==(other)
14
+ name == other.name
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir[File.join(__dir__, "models/**/*.rb")].each { |file| require_relative file }
4
+
5
+ module TraceViz
6
+ module Models
7
+ end
8
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Renderers
5
+ class BaseRenderer
6
+ NodeLine = Struct.new(:data, :line)
7
+
8
+ def initialize(collector, context)
9
+ @collector = collector
10
+ @context = context
11
+ end
12
+
13
+ def render
14
+ to_lines.map { |line| line[:line] }.join("\n")
15
+ end
16
+
17
+ # [ { line: 'line1' }, { line: 'line2' } ]
18
+ def to_lines
19
+ []
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :collector, :context
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../base_renderer"
4
+ require "trace_viz/builders/diagram/sequence_builder"
5
+ require "trace_viz/syntax/mermaid/sequence_syntax"
6
+
7
+ module TraceViz
8
+ module Renderers
9
+ module Diagram
10
+ class SequenceRenderer < BaseRenderer
11
+ def initialize(collector, context)
12
+ super(collector, context)
13
+
14
+ @builder = Builders::Diagram::SequenceBuilder.new(collector)
15
+ @syntax = Syntax::Mermaid::SequenceSyntax.new
16
+ @diagram = builder.build
17
+ end
18
+
19
+ def to_lines
20
+ [
21
+ header_line,
22
+ *render_boxes,
23
+ *render_messages,
24
+ ]
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :builder, :diagram, :syntax
30
+
31
+ def header_line
32
+ NodeLine.new(nil, syntax.header)
33
+ end
34
+
35
+ def render_boxes
36
+ diagram.boxes.flat_map { |box| render_box(box) }
37
+ end
38
+
39
+ def render_messages
40
+ diagram.messages.map { |message| NodeLine.new(nil, syntax.message(message)) }
41
+ end
42
+
43
+ def render_box(box)
44
+ [
45
+ NodeLine.new(nil, syntax.box_start(box)),
46
+ *render_participants(box),
47
+ NodeLine.new(nil, syntax.box_end(box)),
48
+ ]
49
+ end
50
+
51
+ def render_participants(box)
52
+ box.participants.map do |participant|
53
+ NodeLine.new(nil, syntax.participant(participant))
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Renderers
5
+ class RenderContext
6
+ attr_reader :formatter_factory
7
+
8
+ def initialize(formatter_factory:)
9
+ @formatter_factory = formatter_factory
10
+ end
11
+
12
+ def fetch_formatter(key)
13
+ formatter_factory.fetch_formatter(key)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "render_context"
4
+ require_relative "renderer_factory"
5
+
6
+ module TraceViz
7
+ module Renderers
8
+ class RendererBuilder
9
+ class << self
10
+ def build(collector, key:, formatter_factory:)
11
+ raise ArgumentError, "Renderer key must be provided" if key.nil?
12
+
13
+ render_context = RenderContext.new(formatter_factory: formatter_factory)
14
+ renderer_factory = RendererFactory.new(collector, render_context)
15
+ renderer_factory.build(key)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "verbose_renderer"
4
+ require_relative "summary_renderer"
5
+ require_relative "diagram/sequence_renderer"
6
+
7
+ module TraceViz
8
+ module Renderers
9
+ class RendererFactory
10
+ RENDERERS = {
11
+ verbose: VerboseRenderer,
12
+ summary: SummaryRenderer,
13
+ sequence_diagram: Diagram::SequenceRenderer,
14
+ }.freeze
15
+
16
+ def initialize(collector, context)
17
+ @collector = collector
18
+ @context = context
19
+ end
20
+
21
+ def build(key)
22
+ renderer_class = RENDERERS[key]
23
+ raise ArgumentError, "Invalid renderer key: #{key}" unless renderer_class
24
+
25
+ renderer_class.new(@collector, @context)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_renderer"
4
+ require "trace_viz/transformers/summary_transformer"
5
+
6
+ module TraceViz
7
+ module Renderers
8
+ class SummaryRenderer < BaseRenderer
9
+ def to_lines
10
+ render_nodes(data.children)
11
+ end
12
+
13
+ private
14
+
15
+ def data
16
+ Transformers::SummaryTransformer.new(collector).transform
17
+ end
18
+
19
+ def render_nodes(nodes)
20
+ nodes.flat_map { |node| render_node(node) }
21
+ end
22
+
23
+ def render_node(node)
24
+ node_line = NodeLine.new(node.data, format_node(node.data))
25
+
26
+ [node_line] + render_nodes(node.children)
27
+ end
28
+
29
+ def format_node(data)
30
+ context.fetch_formatter(data.key).call(data)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_renderer"
4
+
5
+ module TraceViz
6
+ module Renderers
7
+ class VerboseRenderer < BaseRenderer
8
+ def to_lines
9
+ traverse_data(data)
10
+ end
11
+
12
+ private
13
+
14
+ def data
15
+ collector.collection
16
+ end
17
+
18
+ def traverse_data(data)
19
+ data.map do |trace_data|
20
+ NodeLine.new(trace_data, format_for(trace_data))
21
+ end
22
+ end
23
+
24
+ def format_for(trace_data)
25
+ context.fetch_formatter(trace_data.key).call(trace_data)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Shared
5
+ module RendererHelper
6
+ def process_lines(lines, &block)
7
+ return [] unless lines.is_a?(Array)
8
+
9
+ lines.map do |line|
10
+ validate_line_structure!(line)
11
+ block.call(line)
12
+ end.compact
13
+ end
14
+
15
+ private
16
+
17
+ def validate_line_structure!(line)
18
+ unless line.respond_to?(:line) && line.respond_to?(:data)
19
+ raise ArgumentError,
20
+ "Invalid line structure: #{line.inspect}. Expected an object with :line and :data attributes."
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir[File.join(__dir__, "shared/**/*.rb")].each { |file| require_relative file }
4
+
5
+ module TraceViz
6
+ module Shared
7
+ end
8
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/helpers"
4
+
5
+ module TraceViz
6
+ module Syntax
7
+ module Mermaid
8
+ class SequenceSyntax
9
+ include Helpers::ConfigHelper
10
+
11
+ def header
12
+ "sequenceDiagram"
13
+ end
14
+
15
+ def box_start(box)
16
+ "#{indent}box #{sanitize_name(box.color)} #{sanitize_name(box.description)}"
17
+ end
18
+
19
+ def box_end(_box)
20
+ "#{indent}end"
21
+ end
22
+
23
+ def participant(participant)
24
+ alias_name = sanitize_name(participant.alias_name)
25
+ name = sanitize_name(participant.name)
26
+ "#{indent}participant #{alias_name} as #{name}"
27
+ end
28
+
29
+ def message(message)
30
+ from = sanitize_name(message.from&.alias_name)
31
+ to = sanitize_name(message.to&.alias_name)
32
+ content = sanitize_name(message.content)
33
+
34
+ message_syntax(message.type, from, to, content)
35
+ end
36
+
37
+ private
38
+
39
+ def message_syntax(type, from, to, content)
40
+ case type
41
+ when :call
42
+ "#{indent}#{from} ->> #{to}: #{content}"
43
+ when :return
44
+ "#{indent}#{from} -->> #{to}: #{content}"
45
+ when :activate
46
+ "#{indent}activate #{to}"
47
+ when :deactivate
48
+ "#{indent}deactivate #{to}"
49
+ when :loop_start
50
+ "#{indent}loop #{content}"
51
+ when :loop_end
52
+ "#{indent}end"
53
+ when :note
54
+ "#{indent}Note over #{to}: #{content}"
55
+ else
56
+ raise ArgumentError, "Unsupported message type: #{type}"
57
+ end
58
+ end
59
+
60
+ def indent
61
+ " " * fetch_general_config(:tab_size)
62
+ end
63
+
64
+ def sanitize_name(name)
65
+ return "" if name.nil?
66
+
67
+ # Convert Symbols to Strings and handle string sanitization
68
+ name = name.to_s.dup
69
+
70
+ # Handle class name pattern
71
+ name.sub!(/^#<Class:/, "[Class]")
72
+ name.sub!(/>$/, "")
73
+
74
+ # Replace unconventional method names with readable alternatives
75
+ name.gsub!("[]=", "set_value")
76
+ name.gsub!(/<<\z/, "append")
77
+ name.gsub!("[]", "get_value")
78
+ name.gsub!(/\A=/, "assign")
79
+
80
+ # Escape specific HTML characters in one pass
81
+ name.gsub!(/[<>:]/) do |char|
82
+ case char
83
+ when "<"
84
+ "&lt;"
85
+ when ">"
86
+ "&gt;"
87
+ # when ":"
88
+ # "&#58;"
89
+ else
90
+ char
91
+ end
92
+ end
93
+
94
+ name
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,36 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "trace_viz/context"
3
+ require "trace_viz/helpers"
4
+ require "trace_viz/traits"
4
5
 
5
6
  module TraceViz
6
7
  module TraceData
7
8
  class Base
8
- attr_reader :config,
9
- :timestamp
10
- attr_accessor :depth
9
+ include Helpers::ConfigHelper
10
+ include Traits::DepthTrackable
11
+ include Traits::TimeTrackable
11
12
 
12
13
  def initialize
13
- @config = Context.for(:config).configuration
14
-
15
- @depth = 0
14
+ assign_depth(0)
16
15
  record_timestamp
17
16
  end
18
17
 
19
- # Unique ID for each individual event
20
- def id
21
- raise NotImplementedError
18
+ #
19
+ # Represents trace data type code
20
+ #
21
+ def key
22
+ :base
22
23
  end
23
24
 
24
- # Shared ID betweem events for the same method call
25
- def action_id
25
+ def event
26
26
  raise NotImplementedError
27
27
  end
28
28
 
29
- def action
29
+ def klass
30
30
  raise NotImplementedError
31
31
  end
32
32
 
33
- def event
33
+ def action
34
34
  raise NotImplementedError
35
35
  end
36
36
 
@@ -42,14 +42,14 @@ module TraceViz
42
42
  raise NotImplementedError
43
43
  end
44
44
 
45
- def klass
46
- raise NotImplementedError
47
- end
48
-
49
- private
50
-
51
- def record_timestamp
52
- @timestamp = Time.now
45
+ def to_h
46
+ {
47
+ event: event,
48
+ klass: klass,
49
+ action: action,
50
+ path: path,
51
+ line_number: line_number,
52
+ }
53
53
  end
54
54
  end
55
55
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module TraceViz
6
+ module TraceData
7
+ class Node < Base
8
+ attr_accessor :parent
9
+ attr_reader :children
10
+
11
+ def initialize
12
+ super()
13
+
14
+ @parent = nil
15
+ @children = []
16
+ end
17
+
18
+ def add_child(node)
19
+ node.parent = self
20
+ @children << node
21
+ end
22
+
23
+ def add_children(nodes)
24
+ nodes.each do |node|
25
+ add_child(node)
26
+ end
27
+ end
28
+
29
+ def to_h
30
+ super.merge(
31
+ {
32
+ parent: parent&.to_s,
33
+ children: children.map(&:to_h),
34
+ },
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "node"
4
+
5
+ module TraceViz
6
+ module TraceData
7
+ class RootNode < Node
8
+ def initialize
9
+ super()
10
+
11
+ # Explicitly ensure no parent for root
12
+ @parent = nil
13
+ end
14
+
15
+ def root?
16
+ true
17
+ end
18
+
19
+ def parent=(_parent)
20
+ raise NoMethodError, "RootNode cannot have a parent"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "node"
4
+
5
+ module TraceViz
6
+ module TraceData
7
+ class SummaryNode < Node
8
+ attr_reader :group, :count, :representative_node, :event, :klass, :action, :path, :params, :result
9
+
10
+ def initialize(group:)
11
+ super()
12
+
13
+ @group = group
14
+ @count = group.size
15
+
16
+ @representative_node = group.first
17
+ @depth = representative_node.depth
18
+ @event = representative_node.event
19
+ @klass = representative_node.klass
20
+ @path = representative_node.path
21
+ @action = representative_node.action
22
+
23
+ # Representative node is the first node in the group belonging to MethodCall
24
+ @params = representative_node.params
25
+ @result = representative_node.method_return.result
26
+
27
+ add_children(representative_node.children)
28
+ end
29
+
30
+ def key
31
+ :summary_group
32
+ end
33
+
34
+ def duration
35
+ return 0 if count.zero?
36
+
37
+ total_duration / count
38
+ end
39
+
40
+ def total_duration
41
+ children.map(&:duration).sum
42
+ end
43
+ end
44
+ end
45
+ end