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
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/collectors/filters/registry"
4
+ require_relative "base_step"
5
+
6
+ module TraceViz
7
+ module Collectors
8
+ module Steps
9
+ class ValidationStep < BaseStep
10
+ def initialize
11
+ super()
12
+ @filters = build_filters.freeze
13
+ end
14
+
15
+ def call(trace_data)
16
+ trace_data if pass?(trace_data)
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :filters
22
+
23
+ def pass?(trace_data)
24
+ filters.all? { |filter| filter.apply?(trace_data) }
25
+ end
26
+
27
+ def build_filters
28
+ Collectors::Filters::Registry.build(config.filters)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir[File.join(__dir__, "steps/**/*.rb")].each { |file| require_relative file }
4
+
5
+ module TraceViz
6
+ module Collectors
7
+ module Steps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Collectors
5
+ class TracePipeline
6
+ def initialize
7
+ @steps = []
8
+ end
9
+
10
+ def add_step(step)
11
+ @steps << step
12
+ end
13
+
14
+ def process(trace_data)
15
+ @steps.each do |step|
16
+ trace_data = step.call(trace_data)
17
+ return nil unless trace_data
18
+ end
19
+ trace_data
20
+ rescue StandardError => e
21
+ TraceViz.logger.error("Pipeline processing failed for trace_data ID: #{trace_data.id} - #{e.message}")
22
+ nil
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "trace_pipeline"
4
+ require_relative "steps"
5
+
6
+ module TraceViz
7
+ module Collectors
8
+ class TracePipelineBuilder
9
+ class << self
10
+ def build
11
+ TracePipeline.new.tap do |pipeline|
12
+ pipeline.add_step(Steps::ValidationStep.new)
13
+
14
+ #
15
+ # Those actions require access to the current call,
16
+ # so it needs to be run before current call is updated
17
+ #
18
+ pipeline.add_step(Steps::BuildHierarchyStep.new)
19
+ pipeline.add_step(Steps::LinkingStep.new)
20
+
21
+ pipeline.add_step(Steps::AssignDepthForCallStep.new)
22
+ pipeline.add_step(Steps::AssignDepthForReturnStep.new)
23
+ pipeline.add_step(Steps::HiddenStep.new)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/trace_data/trace_point_builder"
4
+ require_relative "base_collector"
5
+ require_relative "matchers/trace_point_action_matcher"
6
+ require_relative "matchers/within_depth_matcher"
7
+
8
+ module TraceViz
9
+ module Collectors
10
+ class TracePointCollector < BaseCollector
11
+ def initialize
12
+ super()
13
+
14
+ @action_matcher = Matchers::TracePointActionMatcher.new
15
+ @within_depth_matcher = Matchers::WithinDepthMatcher.new
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :action_matcher, :within_depth_matcher
21
+
22
+ def can_collect?(trace_point)
23
+ within_depth? || match_action?(trace_point)
24
+ end
25
+
26
+ def build_trace(trace_point)
27
+ TraceData::TracePointBuilder.build(trace_point)
28
+ end
29
+
30
+ def match_action?(trace_point)
31
+ action_matcher.matches?(trace_point)
32
+ end
33
+
34
+ def within_depth?
35
+ depth = tracker.current_depth
36
+
37
+ within_depth_matcher.matches?(depth)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Collectors
5
+ class TraceStats
6
+ attr_reader :total_traces, :max_depth, :event_counts
7
+
8
+ def initialize
9
+ @total_traces = 0
10
+ @max_depth = 0
11
+ @event_counts = Hash.new(0)
12
+ end
13
+
14
+ def update(trace_data)
15
+ @total_traces += 1
16
+ @max_depth = [@max_depth, trace_data.depth].max
17
+ @event_counts[trace_data.event] += 1
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Config
5
+ class Copier
6
+ def initialize(configuration)
7
+ @origin_configuration = configuration
8
+ @settings = origin_configuration.settings
9
+ end
10
+
11
+ def copy
12
+ copied_settings = deep_copy(settings)
13
+ copy = origin_configuration.class.new
14
+ copied_settings.each { |key, value| copy.update(key, value) }
15
+ copy
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :origin_configuration, :settings
21
+
22
+ def deep_copy(value)
23
+ case value
24
+ when Hash
25
+ value.transform_values { |v| deep_copy(v) }
26
+ when Array
27
+ value.map { |v| deep_copy(v) }
28
+ else
29
+ begin
30
+ value.dup
31
+ rescue TypeError
32
+ value # Return immutable objects as-is
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/collectors/filters/registry"
4
+
5
+ module TraceViz
6
+ module Config
7
+ class Validator
8
+ FILTER_KEYS = Collectors::Filters::Registry::FILTERS.keys.freeze
9
+
10
+ def initialize
11
+ @validations = {
12
+ params: ->(value) { validate_params(value) },
13
+ result: ->(value) { validate_result(value) },
14
+ source_location: ->(value) { validate_source_location(value) },
15
+ filters: ->(value) { validate_filters(value) },
16
+ export: ->(value) { validate_export(value) },
17
+ }
18
+ end
19
+
20
+ def validate(group, value)
21
+ return unless @validations.key?(group)
22
+
23
+ @validations[group].call(value)
24
+ end
25
+
26
+ private
27
+
28
+ def validate_params(value)
29
+ mode = value[:mode]
30
+ unless Defaults::Config.valid_param_mode?(mode)
31
+ raise ArgumentError,
32
+ "Invalid param mode: #{mode}. Valid modes are #{Defaults::Config.valid_param_modes.join(", ")}."
33
+ end
34
+
35
+ if value[:truncate_values] && (!value[:truncate_values].is_a?(Integer) || value[:truncate_values] <= 0)
36
+ raise ArgumentError, "Truncate values must be a positive integer."
37
+ end
38
+ end
39
+
40
+ def validate_result(value)
41
+ if value[:truncate_length] && !value[:truncate_length].is_a?(Integer)
42
+ raise ArgumentError, "Truncate values must be a positive integer."
43
+ end
44
+ end
45
+
46
+ def validate_source_location(value)
47
+ if value[:truncate_length] && (!value[:truncate_length].is_a?(Integer) || value[:truncate_length] <= 0)
48
+ raise ArgumentError, "Truncate length for source_location must be a positive integer."
49
+ end
50
+
51
+ if value[:filter_paths] && !value[:filter_paths].all? { |path| path.is_a?(Regexp) }
52
+ raise ArgumentError, "All filter paths must be regular expressions."
53
+ end
54
+ end
55
+
56
+ def validate_filters(filters)
57
+ unless filters.is_a?(Array)
58
+ raise ArgumentError, "Filters must be an array. Received: #{filters.class.name}"
59
+ end
60
+ end
61
+
62
+ def validate_export(value)
63
+ unless value.is_a?(Hash)
64
+ raise ArgumentError, "Export configuration must be a hash."
65
+ end
66
+
67
+ format = value[:format]
68
+ unless Defaults::Config.valid_export_format?(format)
69
+ raise ArgumentError,
70
+ "Invalid export format: #{format}. Valid formats are #{Defaults::Config.valid_export_formats.join(", ")}."
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -1,47 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "trace_viz/logger"
4
+ require "trace_viz/config/validator"
5
+ require "trace_viz/config/copier"
4
6
 
5
7
  module TraceViz
6
8
  class Configuration
7
- attr_accessor :logger,
8
- :tab_size,
9
- :show_indent,
10
- :show_depth,
11
- :max_display_depth,
12
- :show_method_name,
13
- :show_source_location,
14
- :show_params,
15
- :show_return_value,
16
- :show_execution_time,
17
- :show_trace_events
9
+ attr_reader :logger, :settings
10
+ attr_reader(*Defaults::Config.fetch.keys)
18
11
 
19
12
  def initialize
20
13
  @logger = Logger.new
21
- @tab_size = 2
22
- @show_indent = true
23
- @show_depth = true
24
- @max_display_depth = 3 # Recommended to keep this value between 3 and 5
25
- @show_method_name = true
26
- @show_source_location = false
27
- @show_params = true
28
- @show_return_value = true
29
- @show_execution_time = true
30
- @show_trace_events = [:call, :return]
14
+ @validator = Config::Validator.new
15
+ @settings = Defaults::Config.fetch
16
+ define_dynamic_accessors
17
+ end
18
+
19
+ def [](key)
20
+ settings[key]
21
+ end
22
+
23
+ def update(group, values)
24
+ raise ArgumentError, "Invalid configuration group: #{group}" unless settings.key?(group)
25
+
26
+ @validator.validate(group, values)
27
+ if settings[group].is_a?(Hash)
28
+ settings[group].merge!(values)
29
+ else
30
+ settings[group] = values
31
+ end
32
+ end
33
+
34
+ def reset_defaults
35
+ @settings = Defaults::Config.fetch
31
36
  end
32
37
 
33
38
  def dup
34
- copy = self.class.new
35
- instance_variables.each do |var|
36
- value = instance_variable_get(var)
37
- copy_value = begin
38
- value.dup
39
- rescue TypeError
40
- value
39
+ Config::Copier.new(self).copy
40
+ end
41
+
42
+ private
43
+
44
+ def define_dynamic_accessors
45
+ settings.each_key do |attr|
46
+ define_singleton_method(attr) { settings[attr] }
47
+ define_singleton_method("#{attr}=") do |value|
48
+ update(attr, value)
41
49
  end
42
- copy.instance_variable_set(var, copy_value)
43
50
  end
44
- copy
45
51
  end
46
52
  end
47
53
 
@@ -23,7 +23,7 @@ module TraceViz
23
23
  if temp_configuration.respond_to?("#{key}=")
24
24
  temp_configuration.send("#{key}=", value)
25
25
  else
26
- warn("TraceViz: Unknown configuration option '#{key}'")
26
+ TraceViz.logger.warn("Unknown configuration option '#{key}'")
27
27
  end
28
28
  end
29
29
 
@@ -1,37 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "trace_viz/context/manager/context_map"
4
- require "trace_viz/context/manager/context_validation"
5
- require "trace_viz/context/manager/context_registry"
6
- require "trace_viz/context/manager/context_operations"
7
- require "trace_viz/context/config_context"
8
- require "trace_viz/context/tracking_context"
3
+ require "trace_viz/context/map"
4
+ require "trace_viz/context/registry"
9
5
 
10
6
  module TraceViz
11
7
  module Context
12
8
  class Manager
9
+ @map = Map.new
10
+
13
11
  class << self
14
- include ContextMap
15
- include ContextValidation
16
- include ContextRegistry
17
- include ContextOperations
12
+ def enter_contexts(contexts)
13
+ @map.replace(Registry.build(contexts))
14
+ end
18
15
 
19
- # Initialize class instance variables
20
- def initialize_manager
21
- @context_map = {}
22
- @registered_contexts = {}
16
+ def exit_contexts(*keys)
17
+ @map.remove(*keys)
18
+ end
23
19
 
24
- register_default_contexts
20
+ def with_contexts(contexts = {})
21
+ enter_contexts(contexts)
22
+ yield
23
+ ensure
24
+ exit_contexts(*contexts.keys)
25
25
  end
26
26
 
27
- def register_default_contexts
28
- Manager.register_context_type(:config, ConfigContext)
29
- Manager.register_context_type(:tracking, TrackingContext)
27
+ def fetch_context(key)
28
+ @map.fetch(key)
30
29
  end
31
30
  end
32
-
33
- # Ensure initialization upon loading
34
- initialize_manager
35
31
  end
36
32
  end
37
33
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Context
5
+ class Map
6
+ def initialize
7
+ @context_map = {}
8
+ end
9
+
10
+ def replace(new_map)
11
+ @context_map = new_map
12
+ end
13
+
14
+ def fetch(key)
15
+ @context_map.fetch(key)
16
+ rescue KeyError
17
+ raise ContextError, "Context for key '#{key}' not found"
18
+ end
19
+
20
+ def remove(*keys)
21
+ keys.each { |key| @context_map.delete(key) }
22
+ end
23
+
24
+ def reset
25
+ @context_map.clear
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "trace_viz/context/config_context"
4
+ require "trace_viz/context/tracking_context"
5
+
6
+ module TraceViz
7
+ module Context
8
+ class Registry
9
+ CONTEXTS = {
10
+ config: ConfigContext,
11
+ tracking: TrackingContext,
12
+ }.freeze
13
+
14
+ class << self
15
+ # Builds a hash of context objects based on the provided contexts hash.
16
+ #
17
+ # @param [Hash] contexts A hash where the keys are context keys and the values are options for each context.
18
+ # Example:
19
+ # {
20
+ # context_key1: { option1: 'value1', option2: 'value2' },
21
+ # context_key2: { option1: 'value3', option2: 'value4' }
22
+ # }
23
+ #
24
+ # @return [Hash] A hash where the keys are context keys and the values are instantiated context objects.
25
+ #
26
+ # @raise [ArgumentError] If a context key is not found in the CONTEXTS hash.
27
+ def build(contexts)
28
+ contexts.each_with_object({}) do |(context_key, options), result|
29
+ klass = CONTEXTS.fetch(context_key)
30
+
31
+ result[context_key] = klass.new(**(options || {}))
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Context
5
+ module Tracking
6
+ class ActiveCalls
7
+ def initialize
8
+ @stack = []
9
+ end
10
+
11
+ def push(trace_data)
12
+ @stack.push(trace_data)
13
+ end
14
+
15
+ def pop
16
+ @stack.pop
17
+ end
18
+
19
+ def current
20
+ @stack.last
21
+ end
22
+
23
+ def empty?
24
+ @stack.empty?
25
+ end
26
+
27
+ def size
28
+ @stack.size
29
+ end
30
+
31
+ def clear
32
+ @stack.clear
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -2,16 +2,25 @@
2
2
 
3
3
  require "trace_viz/context/base_context"
4
4
  require "trace_viz/context/tracking/depth"
5
+ require "trace_viz/context/tracking/active_calls"
5
6
 
6
7
  module TraceViz
7
8
  module Context
8
9
  class TrackingContext < BaseContext
9
- attr_reader :depth
10
+ attr_reader :active_calls
10
11
 
11
12
  def initialize(**options)
12
13
  super
13
14
 
14
- @depth = Tracking::Depth.new
15
+ @active_calls = Tracking::ActiveCalls.new
16
+ end
17
+
18
+ def current_call
19
+ active_calls.current
20
+ end
21
+
22
+ def current_depth
23
+ active_calls.size
15
24
  end
16
25
  end
17
26
  end
@@ -5,8 +5,8 @@ require "trace_viz/context/manager"
5
5
  module TraceViz
6
6
  module Context
7
7
  class << self
8
- def for(type)
9
- Manager.get_context(type)
8
+ def for(key)
9
+ Manager.fetch_context(key)
10
10
  end
11
11
  end
12
12
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "trace_viz/defaults"
3
4
  require "trace_viz/logger"
4
5
  require "trace_viz/context"
5
6
  require "trace_viz/configuration"
@@ -9,6 +10,8 @@ module TraceViz
9
10
  module Core
10
11
  class Tracer
11
12
  def trace(**options, &block)
13
+ Defaults::Themes.apply_solarized_theme
14
+
12
15
  Context::Manager.with_contexts(config: options, tracking: {}) do
13
16
  adapter = Adapters::TracePointAdapter.new
14
17
  adapter.trace(&block)
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TraceViz
4
+ module Defaults
5
+ class Actions
6
+ EMOJIS = {
7
+ default: "",
8
+ info: "ℹ️",
9
+ success: "✅",
10
+ error: "❌",
11
+ warn: "⚠️",
12
+ start: "🚀",
13
+ processing: "🔄",
14
+ finish: "🏁",
15
+ exported: "📤",
16
+ skipped: "⏩",
17
+ stats: "📊",
18
+ }.freeze
19
+
20
+ COLORS = {
21
+ # Default actions
22
+ default: :reset,
23
+ info: :cyan,
24
+ success: :green,
25
+ error: :bright_red,
26
+ warn: :yellow,
27
+
28
+ # Processing actions
29
+ start: :bright_cyan,
30
+ processing: [:dim, :bright_white],
31
+ finish: :bright_magenta,
32
+
33
+ # Export & stats actions
34
+ exported: :bright_green,
35
+ skipped: :bright_white,
36
+ stats: [:bold, :underline, :bright_white],
37
+
38
+ # Trace data actions
39
+ trace_indent: :dim,
40
+ trace_depth: :blue,
41
+ trace_depth_prefix: [:dim, :italic, :blue],
42
+ trace_depth_open: [:dim, :bright_blue],
43
+ trace_depth_value: :bright_red,
44
+ trace_depth_close: [:dim, :bright_blue],
45
+ trace_method_name: :bright_cyan,
46
+ trace_method_class: :bright_green,
47
+ trace_method_sign: :blue,
48
+ trace_method_action: [:bold, :bright_cyan],
49
+ trace_source_location: [:dim, :bright_white],
50
+ trace_params_key: :bright_yellow,
51
+ trace_params_value: [:dim, :bright_yellow],
52
+ trace_result_prefix: [:italic, :bright_blue],
53
+ trace_result_value: :bright_white,
54
+ trace_execution_time: [:dim, :bright_red],
55
+ }.freeze
56
+
57
+ class << self
58
+ def emojis
59
+ EMOJIS
60
+ end
61
+
62
+ def colors
63
+ COLORS
64
+ end
65
+
66
+ def keys
67
+ colors.keys
68
+ end
69
+
70
+ def emoji_for(action)
71
+ EMOJIS.fetch(action, EMOJIS[:default])
72
+ end
73
+
74
+ def source_colors
75
+ Defaults.action_colors || COLORS
76
+ end
77
+
78
+ def colors_for(action)
79
+ Array(source_colors.fetch(action, source_colors[:default]))
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end