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.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +34 -0
- data/README.md +134 -39
- data/Steepfile +34 -0
- data/examples/eu_central_bank.rb +69 -0
- data/examples/example.cast +189 -0
- data/examples/example.rb +94 -23
- data/lib/trace_viz/adapters/base_adapter.rb +23 -2
- data/lib/trace_viz/adapters/trace_point_adapter.rb +10 -11
- data/lib/trace_viz/collectors/base_collector.rb +90 -0
- data/lib/trace_viz/collectors/filters/base_class_filter.rb +29 -0
- data/lib/trace_viz/collectors/filters/base_exclude_filter.rb +16 -0
- data/lib/trace_viz/collectors/filters/base_filter.rb +17 -0
- data/lib/trace_viz/collectors/filters/base_include_filter.rb +16 -0
- data/lib/trace_viz/collectors/filters/exclude_classes_filter.rb +15 -0
- data/lib/trace_viz/collectors/filters/exclude_default_classes_filter.rb +34 -0
- data/lib/trace_viz/collectors/filters/exclude_gems_filter.rb +30 -0
- data/lib/trace_viz/collectors/filters/exclude_internal_call_filter.rb +31 -0
- data/lib/trace_viz/collectors/filters/exclude_rails_framework_filter.rb +38 -0
- data/lib/trace_viz/collectors/filters/include_classes_filter.rb +15 -0
- data/lib/trace_viz/collectors/filters/include_gems_filter.rb +54 -0
- data/lib/trace_viz/collectors/filters/registry.rb +59 -0
- data/lib/trace_viz/collectors/hierarchy_linker.rb +30 -0
- data/lib/trace_viz/collectors/matchers/base_matcher.rb +13 -0
- data/lib/trace_viz/collectors/matchers/trace_point_action_matcher.rb +38 -0
- data/lib/trace_viz/collectors/matchers/within_depth_matcher.rb +26 -0
- data/lib/trace_viz/collectors/steps/assign_depth_for_call_step.rb +30 -0
- data/lib/trace_viz/collectors/steps/assign_depth_for_return_step.rb +39 -0
- data/lib/trace_viz/collectors/steps/base_step.rb +27 -0
- data/lib/trace_viz/collectors/steps/build_hierarchy_step.rb +32 -0
- data/lib/trace_viz/collectors/steps/hidden_step.rb +25 -0
- data/lib/trace_viz/collectors/steps/linking_step.rb +36 -0
- data/lib/trace_viz/collectors/steps/validation_step.rb +33 -0
- data/lib/trace_viz/collectors/steps.rb +10 -0
- data/lib/trace_viz/collectors/trace_pipeline.rb +26 -0
- data/lib/trace_viz/collectors/trace_pipeline_builder.rb +29 -0
- data/lib/trace_viz/collectors/trace_point_collector.rb +41 -0
- data/lib/trace_viz/collectors/trace_stats.rb +21 -0
- data/lib/trace_viz/config/copier.rb +38 -0
- data/lib/trace_viz/config/validator.rb +75 -0
- data/lib/trace_viz/configuration.rb +36 -30
- data/lib/trace_viz/context/config_context.rb +1 -1
- data/lib/trace_viz/context/manager.rb +17 -21
- data/lib/trace_viz/context/map.rb +29 -0
- data/lib/trace_viz/context/registry.rb +37 -0
- data/lib/trace_viz/context/tracking/active_calls.rb +37 -0
- data/lib/trace_viz/context/tracking_context.rb +11 -2
- data/lib/trace_viz/context.rb +2 -2
- data/lib/trace_viz/core/tracer.rb +3 -0
- data/lib/trace_viz/defaults/actions.rb +84 -0
- data/lib/trace_viz/defaults/colors.rb +61 -0
- data/lib/trace_viz/defaults/config.rb +89 -0
- data/lib/trace_viz/defaults/themes.rb +66 -0
- data/lib/trace_viz/defaults.rb +20 -0
- data/lib/trace_viz/exporters/base_exporter.rb +81 -0
- data/lib/trace_viz/exporters/export_manager.rb +33 -0
- data/lib/trace_viz/exporters/registry.rb +25 -0
- data/lib/trace_viz/exporters/text_exporter.rb +37 -0
- data/lib/trace_viz/formatters/base_formatter.rb +15 -0
- data/lib/trace_viz/formatters/export/base_formatter.rb +12 -0
- data/lib/trace_viz/formatters/export/formatter_factory.rb +27 -0
- data/lib/trace_viz/formatters/export/method_call_formatter.rb +21 -0
- data/lib/trace_viz/formatters/export/method_return_formatter.rb +22 -0
- data/lib/trace_viz/formatters/export/summary_group_formatter.rb +35 -0
- data/lib/trace_viz/formatters/helpers/depth_helper.rb +15 -0
- data/lib/trace_viz/formatters/helpers/indent_helper.rb +15 -0
- data/lib/trace_viz/formatters/helpers/log/color_helper.rb +23 -0
- data/lib/trace_viz/formatters/helpers/log/depth_helper.rb +22 -0
- data/lib/trace_viz/formatters/helpers/log/method_name_helper.rb +29 -0
- data/lib/trace_viz/formatters/helpers/log/params_helper.rb +51 -0
- data/lib/trace_viz/formatters/helpers/log/result_helper.rb +27 -0
- data/lib/trace_viz/formatters/helpers/log/summary/params_helper.rb +53 -0
- data/lib/trace_viz/formatters/helpers/method_details_helper.rb +15 -0
- data/lib/trace_viz/formatters/helpers/params_helper.rb +43 -0
- data/lib/trace_viz/formatters/helpers/result_helper.rb +21 -0
- data/lib/trace_viz/formatters/helpers/source_helper.rb +22 -0
- data/lib/trace_viz/formatters/helpers/summary/params_helper.rb +41 -0
- data/lib/trace_viz/formatters/helpers/summary/source_helper.rb +24 -0
- data/lib/trace_viz/formatters/helpers/time_helper.rb +15 -0
- data/lib/trace_viz/formatters/helpers.rb +10 -0
- data/lib/trace_viz/formatters/log/base_formatter.rb +13 -0
- data/lib/trace_viz/formatters/log/formatter_factory.rb +27 -0
- data/lib/trace_viz/formatters/log/method_call_formatter.rb +34 -0
- data/lib/trace_viz/formatters/log/method_return_formatter.rb +24 -0
- data/lib/trace_viz/formatters/log/summary_group_formatter.rb +40 -0
- data/lib/trace_viz/formatters/log/verbose_formatter.rb +14 -0
- data/lib/trace_viz/formatters/trace_data_formatter.rb +24 -0
- data/lib/trace_viz/helpers/config_helper.rb +13 -0
- data/lib/trace_viz/helpers/trace_point/param_helper.rb +98 -0
- data/lib/trace_viz/helpers/tracking_helper.rb +26 -0
- data/lib/trace_viz/helpers.rb +9 -0
- data/lib/trace_viz/logger.rb +28 -49
- data/lib/trace_viz/loggers/base_logger.rb +29 -0
- data/lib/trace_viz/loggers/log_level_resolver.rb +18 -0
- data/lib/trace_viz/loggers/logging_manager.rb +46 -0
- data/lib/trace_viz/loggers/post_collection_logger.rb +39 -0
- data/lib/trace_viz/loggers/trace_logger.rb +37 -0
- data/lib/trace_viz/loggers/trace_stats_logger.rb +47 -0
- data/lib/trace_viz/renderers/base_renderer.rb +24 -0
- data/lib/trace_viz/renderers/render_context.rb +18 -0
- data/lib/trace_viz/renderers/renderer_factory.rb +41 -0
- data/lib/trace_viz/renderers/summary/node_processor.rb +82 -0
- data/lib/trace_viz/renderers/summary_renderer.rb +22 -0
- data/lib/trace_viz/renderers/verbose_renderer.rb +29 -0
- data/lib/trace_viz/shared/renderer_helper.rb +46 -0
- data/lib/trace_viz/shared.rb +8 -0
- data/lib/trace_viz/trace_data/base.rb +49 -0
- data/lib/trace_viz/trace_data/node.rb +33 -0
- data/lib/trace_viz/trace_data/root_node.rb +20 -0
- data/lib/trace_viz/trace_data/summary_node.rb +49 -0
- data/lib/trace_viz/trace_data/trace_point/base.rb +59 -0
- data/lib/trace_viz/trace_data/trace_point/method_call.rb +47 -0
- data/lib/trace_viz/trace_data/trace_point/method_return.rb +45 -0
- data/lib/trace_viz/trace_data/trace_point_builder.rb +23 -0
- data/lib/trace_viz/traits/depth_trackable.rb +13 -0
- data/lib/trace_viz/traits/identifiable.rb +25 -0
- data/lib/trace_viz/traits/time_trackable.rb +13 -0
- data/lib/trace_viz/traits.rb +10 -0
- data/lib/trace_viz/utils/colorize.rb +12 -23
- data/lib/trace_viz/utils/format_utils/key_value_formatter.rb +37 -0
- data/lib/trace_viz/utils/format_utils/value_truncator.rb +74 -0
- data/lib/trace_viz/utils/format_utils.rb +24 -0
- data/lib/trace_viz/utils/id_generator.rb +35 -0
- data/lib/trace_viz/version.rb +1 -1
- data/sig/adapters/base_adapter.rbs +11 -0
- data/sig/adapters/trace_point_adapter.rbs +13 -0
- data/sig/collectors/filters/registry.rbs +13 -0
- data/sig/collectors/trace_point_collector.rbs +17 -0
- data/sig/config/copier.rbs +15 -0
- data/sig/config/validator.rbs +18 -0
- data/sig/configuration.rbs +22 -0
- data/sig/context/base_context.rbs +9 -0
- data/sig/context/config_context.rbs +13 -0
- data/sig/context/manager.rbs +10 -0
- data/sig/context/map.rbs +13 -0
- data/sig/context.rbs +5 -0
- data/sig/core/tracer.rbs +7 -0
- data/sig/core.rbs +4 -0
- data/sig/defaults.rbs +17 -0
- data/sig/errors.rbs +13 -0
- data/sig/logger.rbs +33 -0
- data/sig/trace_viz.rbs +1 -2
- data/sig/utils/colorize.rbs +8 -0
- data/sig/utils/format_utils/key_value_formatter.rbs +16 -0
- data/sig/utils/format_utils/value_truncator.rbs +19 -0
- data/sig/utils/format_utils.rbs +8 -0
- data/sig/version.rbs +3 -0
- metadata +140 -16
- data/lib/trace_viz/adapters/trace_point/depth_manager.rb +0 -34
- data/lib/trace_viz/adapters/trace_point/event_handler.rb +0 -36
- data/lib/trace_viz/adapters/trace_point/trace_data.rb +0 -89
- data/lib/trace_viz/adapters/trace_point/trace_formatter.rb +0 -95
- data/lib/trace_viz/adapters/trace_point/trace_logger.rb +0 -44
- data/lib/trace_viz/context/manager/context_map.rb +0 -31
- data/lib/trace_viz/context/manager/context_operations.rb +0 -60
- data/lib/trace_viz/context/manager/context_registry.rb +0 -20
- 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,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
|
-
|
8
|
-
|
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
|
-
@
|
22
|
-
@
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
|
@@ -1,37 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "trace_viz/context/
|
4
|
-
require "trace_viz/context/
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
include ContextOperations
|
12
|
+
def enter_contexts(contexts)
|
13
|
+
@map.replace(Registry.build(contexts))
|
14
|
+
end
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@registered_contexts = {}
|
16
|
+
def exit_contexts(*keys)
|
17
|
+
@map.remove(*keys)
|
18
|
+
end
|
23
19
|
|
24
|
-
|
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
|
28
|
-
|
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 :
|
10
|
+
attr_reader :active_calls
|
10
11
|
|
11
12
|
def initialize(**options)
|
12
13
|
super
|
13
14
|
|
14
|
-
@
|
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
|
data/lib/trace_viz/context.rb
CHANGED
@@ -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
|