trace_viz 0.0.1 → 1.0.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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +34 -0
  3. data/README.md +134 -39
  4. data/Steepfile +34 -0
  5. data/examples/eu_central_bank.rb +69 -0
  6. data/examples/example.cast +189 -0
  7. data/examples/example.rb +94 -23
  8. data/lib/trace_viz/adapters/base_adapter.rb +23 -2
  9. data/lib/trace_viz/adapters/trace_point_adapter.rb +10 -11
  10. data/lib/trace_viz/collectors/base_collector.rb +90 -0
  11. data/lib/trace_viz/collectors/filters/base_class_filter.rb +29 -0
  12. data/lib/trace_viz/collectors/filters/base_exclude_filter.rb +16 -0
  13. data/lib/trace_viz/collectors/filters/base_filter.rb +17 -0
  14. data/lib/trace_viz/collectors/filters/base_include_filter.rb +16 -0
  15. data/lib/trace_viz/collectors/filters/exclude_classes_filter.rb +15 -0
  16. data/lib/trace_viz/collectors/filters/exclude_default_classes_filter.rb +34 -0
  17. data/lib/trace_viz/collectors/filters/exclude_gems_filter.rb +30 -0
  18. data/lib/trace_viz/collectors/filters/exclude_internal_call_filter.rb +31 -0
  19. data/lib/trace_viz/collectors/filters/exclude_rails_framework_filter.rb +38 -0
  20. data/lib/trace_viz/collectors/filters/include_classes_filter.rb +15 -0
  21. data/lib/trace_viz/collectors/filters/include_gems_filter.rb +54 -0
  22. data/lib/trace_viz/collectors/filters/registry.rb +59 -0
  23. data/lib/trace_viz/collectors/hierarchy_linker.rb +30 -0
  24. data/lib/trace_viz/collectors/matchers/base_matcher.rb +13 -0
  25. data/lib/trace_viz/collectors/matchers/trace_point_action_matcher.rb +38 -0
  26. data/lib/trace_viz/collectors/matchers/within_depth_matcher.rb +26 -0
  27. data/lib/trace_viz/collectors/steps/assign_depth_for_call_step.rb +30 -0
  28. data/lib/trace_viz/collectors/steps/assign_depth_for_return_step.rb +39 -0
  29. data/lib/trace_viz/collectors/steps/base_step.rb +27 -0
  30. data/lib/trace_viz/collectors/steps/build_hierarchy_step.rb +32 -0
  31. data/lib/trace_viz/collectors/steps/hidden_step.rb +25 -0
  32. data/lib/trace_viz/collectors/steps/linking_step.rb +36 -0
  33. data/lib/trace_viz/collectors/steps/validation_step.rb +33 -0
  34. data/lib/trace_viz/collectors/steps.rb +10 -0
  35. data/lib/trace_viz/collectors/trace_pipeline.rb +26 -0
  36. data/lib/trace_viz/collectors/trace_pipeline_builder.rb +29 -0
  37. data/lib/trace_viz/collectors/trace_point_collector.rb +41 -0
  38. data/lib/trace_viz/collectors/trace_stats.rb +21 -0
  39. data/lib/trace_viz/config/copier.rb +38 -0
  40. data/lib/trace_viz/config/validator.rb +75 -0
  41. data/lib/trace_viz/configuration.rb +36 -30
  42. data/lib/trace_viz/context/config_context.rb +1 -1
  43. data/lib/trace_viz/context/manager.rb +17 -21
  44. data/lib/trace_viz/context/map.rb +29 -0
  45. data/lib/trace_viz/context/registry.rb +37 -0
  46. data/lib/trace_viz/context/tracking/active_calls.rb +37 -0
  47. data/lib/trace_viz/context/tracking_context.rb +11 -2
  48. data/lib/trace_viz/context.rb +2 -2
  49. data/lib/trace_viz/core/tracer.rb +3 -0
  50. data/lib/trace_viz/defaults/actions.rb +84 -0
  51. data/lib/trace_viz/defaults/colors.rb +61 -0
  52. data/lib/trace_viz/defaults/config.rb +89 -0
  53. data/lib/trace_viz/defaults/themes.rb +66 -0
  54. data/lib/trace_viz/defaults.rb +20 -0
  55. data/lib/trace_viz/exporters/base_exporter.rb +81 -0
  56. data/lib/trace_viz/exporters/export_manager.rb +33 -0
  57. data/lib/trace_viz/exporters/registry.rb +25 -0
  58. data/lib/trace_viz/exporters/text_exporter.rb +37 -0
  59. data/lib/trace_viz/formatters/base_formatter.rb +15 -0
  60. data/lib/trace_viz/formatters/export/base_formatter.rb +12 -0
  61. data/lib/trace_viz/formatters/export/formatter_factory.rb +27 -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 +15 -0
  66. data/lib/trace_viz/formatters/helpers/indent_helper.rb +15 -0
  67. data/lib/trace_viz/formatters/helpers/log/color_helper.rb +23 -0
  68. data/lib/trace_viz/formatters/helpers/log/depth_helper.rb +22 -0
  69. data/lib/trace_viz/formatters/helpers/log/method_name_helper.rb +29 -0
  70. data/lib/trace_viz/formatters/helpers/log/params_helper.rb +51 -0
  71. data/lib/trace_viz/formatters/helpers/log/result_helper.rb +27 -0
  72. data/lib/trace_viz/formatters/helpers/log/summary/params_helper.rb +53 -0
  73. data/lib/trace_viz/formatters/helpers/method_details_helper.rb +15 -0
  74. data/lib/trace_viz/formatters/helpers/params_helper.rb +43 -0
  75. data/lib/trace_viz/formatters/helpers/result_helper.rb +21 -0
  76. data/lib/trace_viz/formatters/helpers/source_helper.rb +22 -0
  77. data/lib/trace_viz/formatters/helpers/summary/params_helper.rb +41 -0
  78. data/lib/trace_viz/formatters/helpers/summary/source_helper.rb +24 -0
  79. data/lib/trace_viz/formatters/helpers/time_helper.rb +15 -0
  80. data/lib/trace_viz/formatters/helpers.rb +10 -0
  81. data/lib/trace_viz/formatters/log/base_formatter.rb +13 -0
  82. data/lib/trace_viz/formatters/log/formatter_factory.rb +27 -0
  83. data/lib/trace_viz/formatters/log/method_call_formatter.rb +34 -0
  84. data/lib/trace_viz/formatters/log/method_return_formatter.rb +24 -0
  85. data/lib/trace_viz/formatters/log/summary_group_formatter.rb +40 -0
  86. data/lib/trace_viz/formatters/log/verbose_formatter.rb +14 -0
  87. data/lib/trace_viz/formatters/trace_data_formatter.rb +24 -0
  88. data/lib/trace_viz/helpers/config_helper.rb +13 -0
  89. data/lib/trace_viz/helpers/trace_point/param_helper.rb +98 -0
  90. data/lib/trace_viz/helpers/tracking_helper.rb +26 -0
  91. data/lib/trace_viz/helpers.rb +9 -0
  92. data/lib/trace_viz/logger.rb +28 -49
  93. data/lib/trace_viz/loggers/base_logger.rb +29 -0
  94. data/lib/trace_viz/loggers/log_level_resolver.rb +18 -0
  95. data/lib/trace_viz/loggers/logging_manager.rb +46 -0
  96. data/lib/trace_viz/loggers/post_collection_logger.rb +39 -0
  97. data/lib/trace_viz/loggers/trace_logger.rb +37 -0
  98. data/lib/trace_viz/loggers/trace_stats_logger.rb +47 -0
  99. data/lib/trace_viz/renderers/base_renderer.rb +24 -0
  100. data/lib/trace_viz/renderers/render_context.rb +18 -0
  101. data/lib/trace_viz/renderers/renderer_factory.rb +41 -0
  102. data/lib/trace_viz/renderers/summary/node_processor.rb +82 -0
  103. data/lib/trace_viz/renderers/summary_renderer.rb +22 -0
  104. data/lib/trace_viz/renderers/verbose_renderer.rb +29 -0
  105. data/lib/trace_viz/shared/renderer_helper.rb +46 -0
  106. data/lib/trace_viz/shared.rb +8 -0
  107. data/lib/trace_viz/trace_data/base.rb +49 -0
  108. data/lib/trace_viz/trace_data/node.rb +33 -0
  109. data/lib/trace_viz/trace_data/root_node.rb +20 -0
  110. data/lib/trace_viz/trace_data/summary_node.rb +49 -0
  111. data/lib/trace_viz/trace_data/trace_point/base.rb +59 -0
  112. data/lib/trace_viz/trace_data/trace_point/method_call.rb +47 -0
  113. data/lib/trace_viz/trace_data/trace_point/method_return.rb +45 -0
  114. data/lib/trace_viz/trace_data/trace_point_builder.rb +23 -0
  115. data/lib/trace_viz/traits/depth_trackable.rb +13 -0
  116. data/lib/trace_viz/traits/identifiable.rb +25 -0
  117. data/lib/trace_viz/traits/time_trackable.rb +13 -0
  118. data/lib/trace_viz/traits.rb +10 -0
  119. data/lib/trace_viz/utils/colorize.rb +12 -23
  120. data/lib/trace_viz/utils/format_utils/key_value_formatter.rb +37 -0
  121. data/lib/trace_viz/utils/format_utils/value_truncator.rb +74 -0
  122. data/lib/trace_viz/utils/format_utils.rb +24 -0
  123. data/lib/trace_viz/utils/id_generator.rb +35 -0
  124. data/lib/trace_viz/version.rb +1 -1
  125. data/sig/adapters/base_adapter.rbs +11 -0
  126. data/sig/adapters/trace_point_adapter.rbs +13 -0
  127. data/sig/collectors/filters/registry.rbs +13 -0
  128. data/sig/collectors/trace_point_collector.rbs +17 -0
  129. data/sig/config/copier.rbs +15 -0
  130. data/sig/config/validator.rbs +18 -0
  131. data/sig/configuration.rbs +22 -0
  132. data/sig/context/base_context.rbs +9 -0
  133. data/sig/context/config_context.rbs +13 -0
  134. data/sig/context/manager.rbs +10 -0
  135. data/sig/context/map.rbs +13 -0
  136. data/sig/context.rbs +5 -0
  137. data/sig/core/tracer.rbs +7 -0
  138. data/sig/core.rbs +4 -0
  139. data/sig/defaults.rbs +17 -0
  140. data/sig/errors.rbs +13 -0
  141. data/sig/logger.rbs +33 -0
  142. data/sig/trace_viz.rbs +1 -2
  143. data/sig/utils/colorize.rbs +8 -0
  144. data/sig/utils/format_utils/key_value_formatter.rbs +16 -0
  145. data/sig/utils/format_utils/value_truncator.rbs +19 -0
  146. data/sig/utils/format_utils.rbs +8 -0
  147. data/sig/version.rbs +3 -0
  148. metadata +140 -16
  149. data/lib/trace_viz/adapters/trace_point/depth_manager.rb +0 -34
  150. data/lib/trace_viz/adapters/trace_point/event_handler.rb +0 -36
  151. data/lib/trace_viz/adapters/trace_point/trace_data.rb +0 -89
  152. data/lib/trace_viz/adapters/trace_point/trace_formatter.rb +0 -95
  153. data/lib/trace_viz/adapters/trace_point/trace_logger.rb +0 -44
  154. data/lib/trace_viz/context/manager/context_map.rb +0 -31
  155. data/lib/trace_viz/context/manager/context_operations.rb +0 -60
  156. data/lib/trace_viz/context/manager/context_registry.rb +0 -20
  157. data/lib/trace_viz/context/manager/context_validation.rb +0 -34
@@ -1,73 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "trace_viz/utils/colorize"
4
+
3
5
  module TraceViz
4
6
  class Logger
5
- COLORS = {
6
- reset: "\e[0m",
7
- info: "\e[34m",
8
- success: "\e[32m",
9
- error: "\e[31m",
10
- warn: "\e[33m",
11
- start: "\e[36m",
12
- finish: "\e[35m",
13
- }.freeze
14
-
15
- EMOJIS = {
16
- info: "ℹ️",
17
- success: "✅",
18
- error: "❌",
19
- warn: "⚠️",
20
- start: "🚀",
21
- finish: "🏁",
22
- }.freeze
23
-
24
- LEVELS = [:info, :success, :error, :warn, :start, :finish].freeze
7
+ LEVELS = Defaults::Actions.keys.freeze
25
8
 
26
9
  def initialize(output: $stdout)
27
10
  @output = output
28
11
  end
29
12
 
30
- def info(message)
31
- log(:info, message)
13
+ LEVELS.each do |level|
14
+ define_method(level) do |message|
15
+ log(message, level)
16
+ end
32
17
  end
33
18
 
34
- def success(message)
35
- log(:success, message)
36
- end
19
+ def log(message, level = :default)
20
+ validate_message!(message)
21
+ validate_level!(level)
37
22
 
38
- def error(message)
39
- log(:error, message)
40
- end
23
+ colors = Defaults::Actions.colors_for(level)
24
+ emoji = Defaults::Actions.emoji_for(level)
41
25
 
42
- def warn(message)
43
- log(:warn, message)
44
- end
26
+ raw_message = build_message(message, level, emoji)
27
+ formatted_message = apply_colors(raw_message, colors)
45
28
 
46
- def start(message)
47
- log(:start, message)
48
- end
49
-
50
- def finish(message)
51
- log(:finish, message)
29
+ @output.puts(formatted_message)
52
30
  end
53
31
 
54
32
  private
55
33
 
56
- def log(level, message)
57
- return unless LEVELS.include?(level)
34
+ def validate_message!(message)
35
+ raise ArgumentError, "Message must be a String" unless message.is_a?(String)
36
+ end
58
37
 
59
- color = COLORS[level] || COLORS[:info]
60
- emoji = EMOJIS[level] || EMOJIS[:info]
38
+ def validate_level!(level)
39
+ raise ArgumentError, "Invalid log level: #{level}" unless LEVELS.include?(level)
40
+ end
61
41
 
62
- # Align emoji and level using fixed-width columns
63
- formatted_message = format(
64
- "#{color}%-3s %-8s#{COLORS[:reset]} %s",
65
- emoji,
66
- "[#{level.to_s.upcase}]",
67
- message,
68
- )
42
+ def build_message(message, level, emoji)
43
+ level_str = level == :default ? "" : "[#{level.to_s.upcase}]"
44
+ merged_emoji_level = "#{emoji} #{level_str}".strip
45
+ format("%s%s", merged_emoji_level, message)
46
+ end
69
47
 
70
- @output.puts(formatted_message)
48
+ def apply_colors(message, colors)
49
+ Utils::Colorize.colorize(message, *colors)
71
50
  end
72
51
  end
73
52
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Loggers
5
+ class BaseLogger
6
+ def initialize
7
+ @logger = TraceViz.logger
8
+ end
9
+
10
+ class << self
11
+ def log(*args)
12
+ new(*args).log
13
+ end
14
+ end
15
+
16
+ def log
17
+ raise NotImplementedError
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :logger
23
+
24
+ def log_message(level, message)
25
+ logger.send(level, message)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Loggers
5
+ class LogLevelResolver
6
+ LOG_LEVELS = {
7
+ call: :start,
8
+ return: :finish,
9
+ }.freeze
10
+
11
+ class << self
12
+ def resolve(trace_data)
13
+ LOG_LEVELS[trace_data.event] || :info
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/helpers"
4
+ require_relative "trace_logger"
5
+ require_relative "post_collection_logger"
6
+ require_relative "trace_stats_logger"
7
+
8
+ module TraceViz
9
+ module Loggers
10
+ class LoggingManager
11
+ include Helpers::ConfigHelper
12
+
13
+ def log_runtime_trace(trace_data)
14
+ return unless runtime_logging_enabled?
15
+
16
+ TraceLogger.log(trace_data)
17
+ end
18
+
19
+ def log_stats(collector)
20
+ return unless stats_logging_enabled?
21
+
22
+ TraceStatsLogger.log(collector)
23
+ end
24
+
25
+ def log_post_collection(collector)
26
+ return unless post_collection_logging_enabled?
27
+
28
+ PostCollectionLogger.log(collector)
29
+ end
30
+
31
+ private
32
+
33
+ def runtime_logging_enabled?
34
+ config.log[:enabled] && config.log[:runtime]
35
+ end
36
+
37
+ def post_collection_logging_enabled?
38
+ config.log[:enabled] && config.log[:post_collection]
39
+ end
40
+
41
+ def stats_logging_enabled?
42
+ config.log[:enabled] && config.log[:stats]
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/formatters/log/formatter_factory"
4
+ require "trace_viz/shared"
5
+ require_relative "base_logger"
6
+ require_relative "log_level_resolver"
7
+
8
+ module TraceViz
9
+ module Loggers
10
+ class PostCollectionLogger < BaseLogger
11
+ include Shared::RendererHelper
12
+
13
+ def initialize(collector)
14
+ super()
15
+
16
+ @collector = collector
17
+ @renderer = build_renderer(collector, Formatters::Log::FormatterFactory)
18
+ end
19
+
20
+ def log
21
+ process_lines(renderer.to_lines) { |line| log_line(line) }
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :collector, :renderer
27
+
28
+ def log_line(line)
29
+ log_message(resolve_log_level(line[:trace_data]), line[:line])
30
+
31
+ process_lines(line[:nested_lines]) { |nested| log_line(nested) }
32
+ end
33
+
34
+ def resolve_log_level(trace_data)
35
+ LogLevelResolver.resolve(trace_data)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_logger"
4
+ require_relative "log_level_resolver"
5
+ require "trace_viz/formatters/log/formatter_factory"
6
+
7
+ module TraceViz
8
+ module Loggers
9
+ class TraceLogger < BaseLogger
10
+ def initialize(trace_data)
11
+ super()
12
+
13
+ @trace_data = trace_data
14
+ end
15
+
16
+ def log
17
+ log_message(log_level, formatted_message)
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :trace_data
23
+
24
+ def log_level
25
+ LogLevelResolver.resolve(trace_data)
26
+ end
27
+
28
+ def formatted_message
29
+ fetch_formatter(trace_data).call(trace_data)
30
+ end
31
+
32
+ def fetch_formatter(trace_data)
33
+ Formatters::Log::FormatterFactory.fetch_formatter(trace_data.event)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_logger"
4
+
5
+ module TraceViz
6
+ module Loggers
7
+ class TraceStatsLogger < BaseLogger
8
+ def initialize(collector)
9
+ super()
10
+ @collector = collector
11
+ @stats = collector.stats
12
+ end
13
+
14
+ def log
15
+ logger.stats(format_stats)
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :stats
21
+
22
+ def format_stats
23
+ [
24
+ total_traces_info,
25
+ max_depth_info,
26
+ event_counts_info,
27
+ ].join(" | ")
28
+ end
29
+
30
+ def total_traces_info
31
+ "Total Traces: #{stats.total_traces}"
32
+ end
33
+
34
+ def max_depth_info
35
+ "Max Depth: #{stats.max_depth}"
36
+ end
37
+
38
+ def event_counts_info
39
+ "Event Counts: [#{formatted_event_counts}]"
40
+ end
41
+
42
+ def formatted_event_counts
43
+ stats.event_counts.map { |event, count| "#{event.capitalize}: #{count}" }.join(", ")
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Renderers
5
+ class BaseRenderer
6
+ def initialize(data, context:)
7
+ @data = data
8
+ @context = context
9
+ end
10
+
11
+ def render
12
+ to_lines.map { |line| line[:line] }.join("\n")
13
+ end
14
+
15
+ def to_lines
16
+ []
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :data, :context
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Renderers
5
+ class RenderContext
6
+ attr_reader :formatter_factory, :group_keys
7
+
8
+ def initialize(formatter_factory:, group_keys: [])
9
+ @formatter_factory = formatter_factory
10
+ @group_keys = group_keys
11
+ end
12
+
13
+ def fetch_formatter(key)
14
+ formatter_factory.fetch_formatter(key)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "verbose_renderer"
4
+ require_relative "summary_renderer"
5
+
6
+ module TraceViz
7
+ module Renderers
8
+ class RendererFactory
9
+ RENDERERS = {
10
+ verbose: VerboseRenderer,
11
+ summary: SummaryRenderer,
12
+ }.freeze
13
+
14
+ class << self
15
+ def build(mode, collector, context:)
16
+ renderer_class = fetch_renderer_class(mode)
17
+ renderer_class.new(determine_input(mode, collector), context: context)
18
+ end
19
+
20
+ private
21
+
22
+ def fetch_renderer_class(mode)
23
+ RENDERERS.fetch(mode) do
24
+ raise ArgumentError, "Unknown mode: #{mode}. Valid modes are: #{RENDERERS.keys.join(", ")}"
25
+ end
26
+ end
27
+
28
+ def determine_input(mode, collector)
29
+ case mode
30
+ when :verbose
31
+ collector.collection
32
+ when :summary
33
+ collector.hierarchy.root
34
+ else
35
+ raise ArgumentError, "Invalid mode for input determination: #{mode}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/trace_data/summary_node"
4
+
5
+ module TraceViz
6
+ module Renderers
7
+ class NodeProcessor
8
+ def initialize(nodes, context)
9
+ @nodes = nodes
10
+ @context = context
11
+ end
12
+
13
+ def process
14
+ grouped_nodes.flat_map { |key, group| render_node_or_group(key, group) }
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :nodes, :context
20
+
21
+ def grouped_nodes
22
+ nodes.group_by { |node| node_key(node) }
23
+ end
24
+
25
+ def group_keys
26
+ context.group_keys
27
+ end
28
+
29
+ def node_key(node)
30
+ group_keys.map { |key| fetch_node_attribute(node, key) }
31
+ end
32
+
33
+ def fetch_node_attribute(node, key)
34
+ node.respond_to?(key) ? node.public_send(key) : nil
35
+ end
36
+
37
+ def render_node_or_group(key, group)
38
+ if group.size > 1
39
+ render_group(key, group)
40
+ else
41
+ render_single_node(group.first)
42
+ end
43
+ end
44
+
45
+ def render_group(key, group)
46
+ representative_node = group.first
47
+ nested_lines = process_nested_nodes(representative_node)
48
+
49
+ [{
50
+ line: format_group_line(group),
51
+ trace_data: representative_node,
52
+ nested_lines: nested_lines,
53
+ }]
54
+ end
55
+
56
+ def render_single_node(node)
57
+ current_line = {
58
+ line: format_node(node),
59
+ trace_data: node,
60
+ nested_lines: process_nested_nodes(node),
61
+ }
62
+
63
+ [current_line]
64
+ end
65
+
66
+ def process_nested_nodes(node)
67
+ return [] unless node.respond_to?(:children) && node.children.any?
68
+
69
+ NodeProcessor.new(node.children, context).process
70
+ end
71
+
72
+ def format_node(node)
73
+ context.fetch_formatter(node.event).call(node)
74
+ end
75
+
76
+ def format_group_line(group)
77
+ node = TraceData::SummaryNode.new(group: group)
78
+ context.fetch_formatter(:summary_group).call(node)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_renderer"
4
+ require_relative "summary/node_processor"
5
+
6
+ module TraceViz
7
+ module Renderers
8
+ class SummaryRenderer < BaseRenderer
9
+ def to_lines
10
+ return [] unless valid_children?(data)
11
+
12
+ NodeProcessor.new(data.children, context).process
13
+ end
14
+
15
+ private
16
+
17
+ def valid_children?(node)
18
+ node.respond_to?(:children) && node.children.any?
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_renderer"
4
+ require "trace_viz/formatters/log/formatter_factory"
5
+
6
+ module TraceViz
7
+ module Renderers
8
+ class VerboseRenderer < BaseRenderer
9
+ def to_lines
10
+ traverse_data(data)
11
+ end
12
+
13
+ private
14
+
15
+ def traverse_data(data)
16
+ data.map do |trace_data|
17
+ {
18
+ line: format_for(trace_data),
19
+ trace_data: trace_data,
20
+ }
21
+ end
22
+ end
23
+
24
+ def format_for(trace_data)
25
+ context.fetch_formatter(trace_data.event).call(trace_data)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/renderers/renderer_factory"
4
+ require "trace_viz/renderers/render_context"
5
+ require "trace_viz/formatters/export/formatter_factory"
6
+ require "trace_viz/formatters/log/formatter_factory"
7
+
8
+ module TraceViz
9
+ module Shared
10
+ module RendererHelper
11
+ def build_renderer(collector, formatter_factory)
12
+ raise ArgumentError, "Collector cannot be nil" unless collector
13
+ raise ArgumentError, "FormatterFactory cannot be nil" unless formatter_factory
14
+
15
+ mode = fetch_config(collector, :mode)
16
+ group_keys = fetch_config(collector, :group_keys)
17
+
18
+ context = Renderers::RenderContext.new(
19
+ formatter_factory: formatter_factory,
20
+ group_keys: group_keys,
21
+ )
22
+ Renderers::RendererFactory.build(mode, collector, context: context)
23
+ end
24
+
25
+ def process_lines(lines, &block)
26
+ return [] unless lines.is_a?(Array)
27
+
28
+ lines.map do |line|
29
+ validate_line_structure!(line)
30
+ block.call(line)
31
+ end.compact
32
+ end
33
+
34
+ private
35
+
36
+ def fetch_config(collector, key)
37
+ collector.config.general[key]
38
+ end
39
+
40
+ def validate_line_structure!(line)
41
+ raise ArgumentError, "Line must be a Hash" unless line.is_a?(Hash)
42
+ raise KeyError, "Line must include a :line key" unless line.key?(:line)
43
+ end
44
+ end
45
+ end
46
+ 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,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/helpers"
4
+ require "trace_viz/traits"
5
+
6
+ module TraceViz
7
+ module TraceData
8
+ class Base
9
+ include Helpers::ConfigHelper
10
+ include Traits::DepthTrackable
11
+ include Traits::TimeTrackable
12
+
13
+ def initialize
14
+ assign_depth(0)
15
+ record_timestamp
16
+ end
17
+
18
+ def event
19
+ raise NotImplementedError
20
+ end
21
+
22
+ def klass
23
+ raise NotImplementedError
24
+ end
25
+
26
+ def action
27
+ raise NotImplementedError
28
+ end
29
+
30
+ def path
31
+ raise NotImplementedError
32
+ end
33
+
34
+ def line_number
35
+ raise NotImplementedError
36
+ end
37
+
38
+ def to_h
39
+ {
40
+ event: event,
41
+ klass: klass,
42
+ action: action,
43
+ path: path,
44
+ line_number: line_number,
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,33 @@
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(child)
19
+ child.parent = self
20
+ @children << child
21
+ end
22
+
23
+ def to_h
24
+ super.merge(
25
+ {
26
+ parent: parent&.to_s,
27
+ children: children.map(&:to_h),
28
+ },
29
+ )
30
+ end
31
+ end
32
+ end
33
+ end