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
@@ -1,14 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../base"
3
+ require "trace_viz/traits"
4
+ require_relative "../node"
4
5
 
5
6
  module TraceViz
6
7
  module TraceData
7
8
  module TracePoint
8
- class Base < TraceData::Base
9
+ class Base < TraceData::Node
10
+ include Traits::Identifiable
11
+
9
12
  attr_reader :trace_point,
10
- :id,
11
- :action_id,
13
+ :memory_id,
12
14
  :event,
13
15
  :klass,
14
16
  :action,
@@ -19,18 +21,32 @@ module TraceViz
19
21
  super()
20
22
 
21
23
  @trace_point = trace_point
22
-
23
- populate_trace_attributes
24
+ populate_attributes
25
+ assign_memory_id
24
26
  assign_ids
25
27
  end
26
28
 
29
+ def key
30
+ event
31
+ end
32
+
27
33
  def duration
28
- # TODO: Implement duration calculation
34
+ 0
35
+ end
36
+
37
+ def to_h
38
+ super.merge(
39
+ {
40
+ id: id,
41
+ action_id: action_id,
42
+ memory_id: memory_id,
43
+ },
44
+ )
29
45
  end
30
46
 
31
47
  private
32
48
 
33
- def populate_trace_attributes
49
+ def populate_attributes
34
50
  @event = trace_point.event
35
51
  @klass = trace_point.defined_class
36
52
  @action = trace_point.callee_id
@@ -38,29 +54,8 @@ module TraceViz
38
54
  @line_number = trace_point.lineno
39
55
  end
40
56
 
41
- def assign_ids
42
- @id = generate_unique_id
43
- @action_id = generate_action_id
44
- end
45
-
46
- def memory_id
47
- trace_point.self.object_id
48
- end
49
-
50
- def generate_unique_id
51
- [
52
- memory_id,
53
- action,
54
- path,
55
- line_number,
56
- ].join("_")
57
- end
58
-
59
- def generate_action_id
60
- [
61
- memory_id,
62
- action,
63
- ].join("_")
57
+ def assign_memory_id
58
+ @memory_id = trace_point.self.object_id
64
59
  end
65
60
  end
66
61
  end
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "trace_viz/helpers/trace_point/param_helper"
3
4
  require_relative "base"
4
5
 
5
6
  module TraceViz
6
7
  module TraceData
7
8
  module TracePoint
8
9
  class MethodCall < Base
9
- attr_reader :params
10
+ include Helpers::TracePoint::ParamHelper
11
+
12
+ attr_reader :params, :method_return
10
13
 
11
14
  def initialize(trace_point)
12
15
  super(trace_point)
@@ -14,27 +17,33 @@ module TraceViz
14
17
  populate_params
15
18
  end
16
19
 
17
- private
20
+ def result
21
+ method_return&.result
22
+ end
18
23
 
19
- def populate_params
20
- @params = extract_params(trace_point.binding)
24
+ def link(method_return)
25
+ @method_return = method_return
21
26
  end
22
27
 
23
- def extract_params(binding)
24
- method = binding.eval("method(:#{action})")
25
- method.parameters.each_with_object({}) do |(_, name), hash|
26
- next unless name
27
- next if name.to_s.include?("*") # Skip invalid or special variable names
28
+ def duration
29
+ return 0 unless method_return
28
30
 
29
- value = safe_local_variable_get(binding, name)
30
- hash[name] = value
31
- end
31
+ method_return.timestamp - timestamp
32
32
  end
33
33
 
34
- def safe_local_variable_get(binding, name)
35
- binding.local_variable_defined?(name) ? binding.local_variable_get(name) : nil
36
- rescue NameError
37
- nil
34
+ def to_h
35
+ super.merge(
36
+ {
37
+ params: params,
38
+ method_return_id: method_return&.id,
39
+ },
40
+ )
41
+ end
42
+
43
+ private
44
+
45
+ def populate_params
46
+ @params = extract_params(trace_point.binding, action)
38
47
  end
39
48
  end
40
49
  end
@@ -6,7 +6,7 @@ module TraceViz
6
6
  module TraceData
7
7
  module TracePoint
8
8
  class MethodReturn < Base
9
- attr_reader :result
9
+ attr_reader :result, :method_call
10
10
 
11
11
  def initialize(trace_point)
12
12
  super(trace_point)
@@ -14,6 +14,26 @@ module TraceViz
14
14
  populate_result
15
15
  end
16
16
 
17
+ def link(method_call)
18
+ @method_call = method_call
19
+ method_call.link(self)
20
+ end
21
+
22
+ def duration
23
+ return 0 unless method_call
24
+
25
+ timestamp - method_call.timestamp
26
+ end
27
+
28
+ def to_h
29
+ super.merge(
30
+ {
31
+ result: result,
32
+ method_call_id: method_call&.id,
33
+ },
34
+ )
35
+ end
36
+
17
37
  private
18
38
 
19
39
  def populate_result
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Traits
5
+ module DepthTrackable
6
+ attr_reader :depth
7
+
8
+ def assign_depth(depth)
9
+ @depth = depth
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/utils/id_generator"
4
+
5
+ module TraceViz
6
+ module Traits
7
+ module Identifiable
8
+ attr_reader :id, :action_id
9
+
10
+ def assign_ids
11
+ @id = Utils::IDGenerator.generate_unique_id(
12
+ memory_id: memory_id,
13
+ action: action,
14
+ path: path,
15
+ line_number: line_number,
16
+ )
17
+
18
+ @action_id = Utils::IDGenerator.generate_action_id(
19
+ memory_id: memory_id,
20
+ action: action,
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Traits
5
+ module TimeTrackable
6
+ attr_reader :timestamp
7
+
8
+ def record_timestamp
9
+ @timestamp = Time.now
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "traits/time_trackable"
4
+ require_relative "traits/depth_trackable"
5
+ require_relative "traits/identifiable"
6
+
7
+ module TraceViz
8
+ module Traits
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/helpers/config_helper"
4
+
5
+ module TraceViz
6
+ module Transformers
7
+ TransformedNode = Struct.new(:data, :children)
8
+
9
+ class BaseTransformer
10
+ include Helpers::ConfigHelper
11
+
12
+ def initialize(collector)
13
+ @collector = collector
14
+ end
15
+
16
+ def transform
17
+ raise NotImplementedError
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :collector
23
+
24
+ def data
25
+ raise NotImplementedError
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/trace_data/summary_node"
4
+ require_relative "base_transformer"
5
+
6
+ module TraceViz
7
+ module Transformers
8
+ class SummaryTransformer < BaseTransformer
9
+ def transform
10
+ return root_node unless valid_children?(root_node)
11
+
12
+ TransformedNode.new(
13
+ root_node,
14
+ transform_nodes(root_node.children),
15
+ )
16
+ end
17
+
18
+ private
19
+
20
+ def valid_children?(node)
21
+ node.respond_to?(:children) && node.children.any?
22
+ end
23
+
24
+ def root_node
25
+ collector.hierarchy.root
26
+ end
27
+
28
+ def transform_nodes(nodes)
29
+ nodes.group_by { |node| node_key(node) }
30
+ .map { |_key, group| transform_group(group) }
31
+ end
32
+
33
+ def node_key(node)
34
+ group_keys.map { |key| fetch_node_attribute(node, key) }
35
+ end
36
+
37
+ def fetch_node_attribute(node, key)
38
+ node.respond_to?(key) ? node.public_send(key) : nil
39
+ end
40
+
41
+ def transform_group(group)
42
+ if group.size > 1
43
+ create_summary_node(group)
44
+ else
45
+ create_single_node(group.first)
46
+ end
47
+ end
48
+
49
+ def create_summary_node(group)
50
+ summary_node = TraceData::SummaryNode.new(group: group)
51
+
52
+ TransformedNode.new(
53
+ summary_node,
54
+ transform_nodes(summary_node.children),
55
+ )
56
+ end
57
+
58
+ def create_single_node(node)
59
+ TransformedNode.new(
60
+ node,
61
+ transform_nodes(node.children),
62
+ )
63
+ end
64
+
65
+ def group_keys
66
+ fetch_general_config(:group_keys)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Utils
5
+ class AliasGenerator
6
+ COMPONENT_DELIMITER = "::"
7
+ ALIAS_DELIMITER = "_"
8
+
9
+ class << self
10
+ #
11
+ # Generates a unique alias for a given name and ensures it doesn't conflict
12
+ # with existing aliases.
13
+ #
14
+ def generate(name:, assigned_aliases:)
15
+ raise ArgumentError, "name cannot be nil" if name.nil?
16
+
17
+ # Break the name into components and extract initials
18
+ alias_candidate = extract_initials(name.to_s)
19
+
20
+ # Ensure the alias is unique
21
+ unique_alias = ensure_unique_alias(
22
+ candidate: alias_candidate,
23
+ assigned_aliases: assigned_aliases,
24
+ original_name: name,
25
+ )
26
+
27
+ # Record the alias in the map
28
+ assigned_aliases[name] = unique_alias
29
+ unique_alias
30
+ end
31
+
32
+ private
33
+
34
+ #
35
+ # Extracts initials from a namespaced string
36
+ #
37
+ def extract_initials(full_name)
38
+ parts = full_name.split(COMPONENT_DELIMITER)
39
+ initials = parts.map { |part| part.scan(/[A-Z]/).join }
40
+ initials.join(ALIAS_DELIMITER)
41
+ end
42
+
43
+ #
44
+ # Ensures the alias is unique by appending a counter if necessary
45
+ #
46
+ def ensure_unique_alias(candidate:, assigned_aliases:, original_name:)
47
+ unique_alias = candidate
48
+ counter = 1
49
+ while assigned_aliases.value?(unique_alias)
50
+ unique_alias = "#{candidate}#{ALIAS_DELIMITER}#{counter}"
51
+ counter += 1
52
+ end
53
+ unique_alias
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -4,17 +4,17 @@ module TraceViz
4
4
  module Utils
5
5
  module Colorize
6
6
  class << self
7
- def colorize(text, *styles)
8
- return text if text.nil? || styles.empty?
7
+ def colorize(text, *colors)
8
+ return text if text.nil? || colors.empty?
9
9
 
10
- "#{build_color_sequence(styles)}#{text}#{Defaults.colors[:reset]}"
10
+ "#{build_color_sequence(colors)}#{text}#{Defaults::Colors.fetch(:default)}"
11
11
  end
12
12
 
13
13
  private
14
14
 
15
- def build_color_sequence(styles)
16
- styles
17
- .map { |style| Defaults.colors[style] }
15
+ def build_color_sequence(colors)
16
+ colors
17
+ .map { |color| Defaults::Colors.fetch(color) }
18
18
  .compact
19
19
  .join
20
20
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Utils
5
+ module Format
6
+ module KeyValueFormatter
7
+ DEFAULT_MODE = :name_and_value
8
+ VALID_MODES = [:name_and_value, :name_only, :value_only].freeze
9
+
10
+ class << self
11
+ def format_pairs(data, mode: DEFAULT_MODE)
12
+ validate_input(data)
13
+ formatter = build_formatter(mode)
14
+ data.map { |key, value| formatter.call(key, value) }.join(", ")
15
+ end
16
+
17
+ private
18
+
19
+ def validate_input(data)
20
+ raise ArgumentError,
21
+ "Expected a Hash for data, but received #{data.class}. Please pass a valid Hash." unless data.is_a?(Hash)
22
+ end
23
+
24
+ def build_formatter(mode)
25
+ unless VALID_MODES.include?(mode)
26
+ raise ArgumentError, "Invalid mode: #{mode}. Valid modes are: #{VALID_MODES.join(", ")}."
27
+ end
28
+
29
+ case mode
30
+ when :name_and_value
31
+ ->(key, value) { "#{key}: #{value}" }
32
+ when :name_only
33
+ ->(key, _) { key.to_s }
34
+ when :value_only
35
+ ->(_, value) { value.to_s }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Utils
5
+ module Format
6
+ module ValueTruncator
7
+ DEFAULT_LENGTH = -1
8
+ VALID_DIRECTIONS = [:start, :end].freeze
9
+
10
+ class << self
11
+ def truncate(value, length: DEFAULT_LENGTH, direction: :end, hash_length: DEFAULT_LENGTH)
12
+ validate_params(length, direction, hash_length)
13
+
14
+ # Skip truncation if length is not positive
15
+ return value unless length.positive?
16
+
17
+ opts = {
18
+ value: value,
19
+ length: length,
20
+ direction: direction,
21
+ hash_length: hash_length,
22
+ }
23
+
24
+ case value
25
+ when String then truncate_string(opts)
26
+ when Array then truncate_array(opts)
27
+ when Hash then truncate_hash(opts)
28
+ else truncate_object(opts)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def validate_params(length, direction, hash_length)
35
+ validate_length(length)
36
+ validate_length(hash_length)
37
+ validate_direction(direction)
38
+ end
39
+
40
+ def validate_length(val)
41
+ return if val.is_a?(Integer) && (val.positive? || val == DEFAULT_LENGTH)
42
+
43
+ raise ArgumentError, "Invalid length: #{val}. Must be a positive Integer or -1."
44
+ end
45
+
46
+ def validate_direction(direction)
47
+ return if VALID_DIRECTIONS.include?(direction)
48
+
49
+ raise ArgumentError, "Invalid direction: #{direction}. Valid options are :start or :end."
50
+ end
51
+
52
+ def truncate_string(opts)
53
+ string = opts[:value]
54
+ length = opts[:length]
55
+ direction = opts[:direction]
56
+
57
+ return string if string.length <= length
58
+
59
+ case direction
60
+ when :start then "...#{string[-length..]}"
61
+ when :end then "#{string[0, length]}..."
62
+ end
63
+ end
64
+
65
+ def truncate_array(opts)
66
+ array = opts[:value]
67
+ length = opts[:length]
68
+
69
+ return array if array.size <= length
70
+
71
+ truncated = array.take(length)
72
+ truncated << "..." if array.size > length
73
+ truncated
74
+ end
75
+
76
+ def truncate_hash(opts)
77
+ hash = opts[:value]
78
+ length = opts[:length]
79
+ direction = opts[:direction]
80
+ hash_length = opts[:hash_length]
81
+
82
+ truncated_keys = hash.keys.take(length)
83
+
84
+ truncated_parts = truncated_keys.map do |key|
85
+ "#{key}: #{truncate(hash[key], **opts.except(:value))}"
86
+ end
87
+
88
+ truncated_parts << "..." if hash.size > length
89
+ format_hash(
90
+ content: truncated_parts.join(", "),
91
+ direction: direction,
92
+ hash_length: hash_length,
93
+ )
94
+ end
95
+
96
+ def format_hash(content:, direction:, hash_length:)
97
+ # Only truncate the final string if hash_length is positive
98
+ return "{#{content}}" unless hash_length.positive?
99
+
100
+ case direction
101
+ when :start then "{...#{content[-hash_length..]}}"
102
+ when :end then "{#{content[0, hash_length]}...}"
103
+ end
104
+ end
105
+
106
+ def truncate_object(opts)
107
+ object = opts[:value]
108
+ length = opts[:length]
109
+ direction = opts[:direction]
110
+
111
+ object_str = object.inspect
112
+ return object_str if object_str.length <= length
113
+
114
+ case direction
115
+ when :start then "#{object.class}(...#{object_str[-length..]})"
116
+ when :end then "#{object.class}(#{object_str[0, length]}...)"
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Utils
5
+ class IDGenerator
6
+ ID_DELIMITER = "|"
7
+ COMPONENT_DELIMITER = ":"
8
+
9
+ class << self
10
+ def generate_unique_id(memory_id:, action:, path:, line_number:)
11
+ join_with_delimiters(
12
+ memory: memory_id,
13
+ action: action,
14
+ path: path,
15
+ line: line_number,
16
+ )
17
+ end
18
+
19
+ def generate_action_id(memory_id:, action:)
20
+ join_with_delimiters(
21
+ memory: memory_id,
22
+ action: action,
23
+ )
24
+ end
25
+
26
+ private
27
+
28
+ def join_with_delimiters(**components)
29
+ components.map { |key, value| "#{key}#{COMPONENT_DELIMITER}#{value}" }
30
+ .join(ID_DELIMITER)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir[File.join(__dir__, "utils/**/*.rb")].each { |file| require_relative file }
4
+
5
+ module TraceViz
6
+ module Utils
7
+ end
8
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TraceViz
4
- VERSION = "0.0.2"
4
+ VERSION = "1.0.1"
5
5
  end
@@ -0,0 +1,11 @@
1
+ module TraceViz
2
+ module Adapters
3
+ class BaseAdapter
4
+ def initialize: () -> void
5
+
6
+ def trace: () -> void
7
+
8
+ private attr_reader config: untyped
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module TraceViz
2
+ module Adapters
3
+ class TracePointAdapter < BaseAdapter
4
+ def initialize: () -> void
5
+
6
+ def trace: () { () -> void } -> void
7
+
8
+ private attr_reader collector: TraceViz::Collectors::TracePointCollector
9
+
10
+ private def exporter: () -> untyped
11
+ end
12
+ end
13
+ end