trace_viz 0.0.1 → 0.0.2
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 +130 -38
- data/examples/example.cast +285 -0
- data/examples/example.rb +94 -23
- data/lib/trace_viz/adapters/base_adapter.rb +0 -2
- data/lib/trace_viz/adapters/trace_point_adapter.rb +17 -11
- data/lib/trace_viz/collectors/base_collector.rb +83 -0
- data/lib/trace_viz/collectors/depth_manager.rb +37 -0
- data/lib/trace_viz/collectors/evaluators/base_evaluator.rb +23 -0
- data/lib/trace_viz/collectors/evaluators/filter_evaluator.rb +30 -0
- data/lib/trace_viz/collectors/evaluators/hidden_evaluator.rb +21 -0
- data/lib/trace_viz/collectors/filters/base_filter.rb +23 -0
- data/lib/trace_viz/collectors/filters/exclude_classes_filter.rb +28 -0
- data/lib/trace_viz/collectors/filters/exclude_default_classes_filter.rb +38 -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 +28 -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/matchers/trace_point_action_matcher.rb +36 -0
- data/lib/trace_viz/collectors/matchers/within_depth_matcher.rb +25 -0
- data/lib/trace_viz/collectors/trace_point_collector.rb +51 -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 +74 -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 +7 -2
- data/lib/trace_viz/context.rb +2 -2
- data/lib/trace_viz/core/tracer.rb +1 -0
- data/lib/trace_viz/defaults.rb +139 -0
- data/lib/trace_viz/exporters/base_exporter.rb +84 -0
- data/lib/trace_viz/exporters/formatters/base_formatter.rb +12 -0
- data/lib/trace_viz/exporters/formatters/method_call_formatter.rb +21 -0
- data/lib/trace_viz/exporters/formatters/method_return_formatter.rb +22 -0
- data/lib/trace_viz/exporters/text_exporter.rb +15 -0
- data/lib/trace_viz/exporters/transformers/base_transformer.rb +25 -0
- data/lib/trace_viz/exporters/transformers/text_transformer.rb +28 -0
- data/lib/trace_viz/formatters/base_formatter.rb +42 -0
- data/lib/trace_viz/formatters/helpers/depth_helper.rb +21 -0
- data/lib/trace_viz/formatters/helpers/indent_helper.rb +15 -0
- data/lib/trace_viz/formatters/helpers/method_details_helper.rb +15 -0
- data/lib/trace_viz/formatters/helpers/params_helper.rb +26 -0
- data/lib/trace_viz/formatters/helpers/result_helper.rb +21 -0
- data/lib/trace_viz/formatters/helpers/source_helper.rb +21 -0
- data/lib/trace_viz/formatters/helpers/time_helper.rb +15 -0
- data/lib/trace_viz/logger.rb +37 -47
- data/lib/trace_viz/loggers/trace_builder.rb +30 -0
- data/lib/trace_viz/loggers/trace_formatters/base_formatter.rb +32 -0
- data/lib/trace_viz/loggers/trace_formatters/method_call_formatter.rb +21 -0
- data/lib/trace_viz/loggers/trace_formatters/method_return_formatter.rb +22 -0
- data/lib/trace_viz/loggers/trace_logger.rb +38 -0
- data/lib/trace_viz/loggers/trace_stats_logger.rb +33 -0
- data/lib/trace_viz/trace_data/base.rb +56 -0
- data/lib/trace_viz/trace_data/trace_point/base.rb +68 -0
- data/lib/trace_viz/trace_data/trace_point/method_call.rb +42 -0
- data/lib/trace_viz/trace_data/trace_point/method_return.rb +25 -0
- data/lib/trace_viz/trace_data/trace_point_builder.rb +23 -0
- data/lib/trace_viz/utils/colorize.rb +12 -23
- data/lib/trace_viz/utils/format_utils.rb +67 -0
- data/lib/trace_viz/version.rb +1 -1
- metadata +58 -13
- 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,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,74 @@
|
|
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.valid_param_modes.include?(mode)
|
31
|
+
raise ArgumentError, "Invalid param mode: #{mode}. Valid modes are #{Defaults.valid_param_modes.join(", ")}."
|
32
|
+
end
|
33
|
+
|
34
|
+
if value[:truncate_values] && (!value[:truncate_values].is_a?(Integer) || value[:truncate_values] <= 0)
|
35
|
+
raise ArgumentError, "Truncate values must be a positive integer."
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate_result(value)
|
40
|
+
if value[:truncate_length] && (!value[:truncate_length].is_a?(Integer) || value[:truncate_length] <= 0)
|
41
|
+
raise ArgumentError, "Truncate values must be a positive integer."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_source_location(value)
|
46
|
+
if value[:truncate_length] && (!value[:truncate_length].is_a?(Integer) || value[:truncate_length] <= 0)
|
47
|
+
raise ArgumentError, "Truncate length for source_location must be a positive integer."
|
48
|
+
end
|
49
|
+
|
50
|
+
if value[:filter_paths] && !value[:filter_paths].all? { |path| path.is_a?(Regexp) }
|
51
|
+
raise ArgumentError, "All filter paths must be regular expressions."
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate_filters(filters)
|
56
|
+
unless filters.is_a?(Array)
|
57
|
+
raise ArgumentError, "Filters must be an array. Received: #{filters.class.name}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_export(value)
|
62
|
+
unless value.is_a?(Hash)
|
63
|
+
raise ArgumentError, "Export configuration must be a hash."
|
64
|
+
end
|
65
|
+
|
66
|
+
format = value[:format]
|
67
|
+
unless Defaults.valid_export_formats.include?(format)
|
68
|
+
raise ArgumentError,
|
69
|
+
"Invalid export format: #{format}. Valid formats are #{Defaults.valid_export_formats.join(", ")}."
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
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.fetch_defaults.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.fetch_defaults
|
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.fetch_defaults
|
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,21 @@
|
|
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_depth
|
19
|
+
active_calls.size
|
15
20
|
end
|
16
21
|
end
|
17
22
|
end
|
data/lib/trace_viz/context.rb
CHANGED
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TraceViz
|
4
|
+
class Defaults
|
5
|
+
COLORS = {
|
6
|
+
reset: "\e[0m",
|
7
|
+
bold: "\e[1m",
|
8
|
+
dim: "\e[2m",
|
9
|
+
underline: "\e[4m",
|
10
|
+
reverse: "\e[7m",
|
11
|
+
black: "\e[30m",
|
12
|
+
red: "\e[31m",
|
13
|
+
green: "\e[32m",
|
14
|
+
yellow: "\e[33m",
|
15
|
+
blue: "\e[34m",
|
16
|
+
magenta: "\e[35m",
|
17
|
+
cyan: "\e[36m",
|
18
|
+
light_gray: "\e[37m",
|
19
|
+
dark_gray: "\e[90m",
|
20
|
+
light_red: "\e[91m",
|
21
|
+
light_green: "\e[92m",
|
22
|
+
light_yellow: "\e[93m",
|
23
|
+
light_blue: "\e[94m",
|
24
|
+
light_magenta: "\e[95m",
|
25
|
+
light_cyan: "\e[96m",
|
26
|
+
white: "\e[97m",
|
27
|
+
dim_light_gray: "\e[2;37m",
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
ACTION_EMOJIS = {
|
31
|
+
default: "",
|
32
|
+
info: "ℹ️",
|
33
|
+
success: "✅",
|
34
|
+
error: "❌",
|
35
|
+
warn: "⚠️",
|
36
|
+
start: "🚀",
|
37
|
+
processing: "🔄",
|
38
|
+
finish: "🏁",
|
39
|
+
exported: "📤",
|
40
|
+
skipped: "⏩",
|
41
|
+
stats: "📊",
|
42
|
+
}.freeze
|
43
|
+
|
44
|
+
ACTION_COLORS = {
|
45
|
+
default: :reset,
|
46
|
+
info: :cyan,
|
47
|
+
success: :green,
|
48
|
+
error: :light_red,
|
49
|
+
warn: :yellow,
|
50
|
+
start: :light_cyan,
|
51
|
+
processing: :dim_light_gray,
|
52
|
+
finish: :light_magenta,
|
53
|
+
exported: :light_green,
|
54
|
+
skipped: :dark_gray,
|
55
|
+
stats: :underline,
|
56
|
+
}.freeze
|
57
|
+
|
58
|
+
CONFIG = {
|
59
|
+
general: {
|
60
|
+
tab_size: 2,
|
61
|
+
show_indent: true,
|
62
|
+
show_depth: true,
|
63
|
+
max_display_depth: 3,
|
64
|
+
show_method_name: true,
|
65
|
+
},
|
66
|
+
source_location: {
|
67
|
+
show: false,
|
68
|
+
truncate_length: 100,
|
69
|
+
},
|
70
|
+
params: {
|
71
|
+
show: true,
|
72
|
+
mode: :name_and_value,
|
73
|
+
truncate_values: 50,
|
74
|
+
},
|
75
|
+
result: {
|
76
|
+
show: true,
|
77
|
+
truncate_length: 50,
|
78
|
+
},
|
79
|
+
execution: {
|
80
|
+
show_time: true,
|
81
|
+
show_trace_events: [:call, :return],
|
82
|
+
},
|
83
|
+
filters: [
|
84
|
+
:exclude_internal_call,
|
85
|
+
# :exclude_default_classes,
|
86
|
+
# :exclude_rails_framework,
|
87
|
+
# include_classes: {
|
88
|
+
# classes: [],
|
89
|
+
# },
|
90
|
+
# exclude_classes: {
|
91
|
+
# classes: [],
|
92
|
+
# },
|
93
|
+
# include_gems: {
|
94
|
+
# app_running: true,
|
95
|
+
# app_path: Dir.pwd,
|
96
|
+
# gems: [],
|
97
|
+
# },
|
98
|
+
# exclude_gems: {
|
99
|
+
# gems: [],
|
100
|
+
# },
|
101
|
+
],
|
102
|
+
export: {
|
103
|
+
enabled: true,
|
104
|
+
path: "tmp",
|
105
|
+
format: :txt,
|
106
|
+
overwrite: false,
|
107
|
+
},
|
108
|
+
}.freeze
|
109
|
+
|
110
|
+
VALID_PARAM_MODES = [:name_and_value, :name_only, :value_only].freeze
|
111
|
+
VALID_EXPORT_FORMATS = [:txt, :json, :yml].freeze
|
112
|
+
|
113
|
+
class << self
|
114
|
+
def colors
|
115
|
+
COLORS
|
116
|
+
end
|
117
|
+
|
118
|
+
def action_colors
|
119
|
+
ACTION_COLORS
|
120
|
+
end
|
121
|
+
|
122
|
+
def action_emojis
|
123
|
+
ACTION_EMOJIS
|
124
|
+
end
|
125
|
+
|
126
|
+
def fetch_defaults
|
127
|
+
CONFIG.dup
|
128
|
+
end
|
129
|
+
|
130
|
+
def valid_param_modes
|
131
|
+
VALID_PARAM_MODES
|
132
|
+
end
|
133
|
+
|
134
|
+
def valid_export_formats
|
135
|
+
VALID_EXPORT_FORMATS
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
|
5
|
+
require "trace_viz/context"
|
6
|
+
require_relative "transformers/text_transformer"
|
7
|
+
|
8
|
+
module TraceViz
|
9
|
+
module Exporters
|
10
|
+
class BaseExporter
|
11
|
+
def initialize(collector)
|
12
|
+
@config = Context.for(:config).configuration
|
13
|
+
@export_config = config.export
|
14
|
+
@logger = config.logger
|
15
|
+
@data = transform_collector_data(collector)
|
16
|
+
end
|
17
|
+
|
18
|
+
def export
|
19
|
+
unless export_enabled?
|
20
|
+
logger.warn("Export is disabled in configuration. Skipping export process.")
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
ensure_directory_exists
|
25
|
+
return if handle_empty_content == :skip
|
26
|
+
return if handle_existing_file == :skip
|
27
|
+
|
28
|
+
write_file(content)
|
29
|
+
|
30
|
+
logger.exported("Data successfully exported to #{file_path}")
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
attr_reader :config, :export_config, :logger, :data
|
36
|
+
|
37
|
+
def transform_collector_data(collector)
|
38
|
+
transformer = Transformers::TextTransformer.new(collector)
|
39
|
+
transformer.transform
|
40
|
+
end
|
41
|
+
|
42
|
+
def content
|
43
|
+
raise NotImplementedError
|
44
|
+
end
|
45
|
+
|
46
|
+
def export_enabled?
|
47
|
+
export_config[:enabled]
|
48
|
+
end
|
49
|
+
|
50
|
+
def ensure_directory_exists
|
51
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
52
|
+
end
|
53
|
+
|
54
|
+
def handle_existing_file
|
55
|
+
return unless File.exist?(file_path)
|
56
|
+
|
57
|
+
if export_config[:overwrite]
|
58
|
+
logger.processing("Overwriting existing file: #{file_path}")
|
59
|
+
else
|
60
|
+
logger.skipped("File already exists and overwrite is disabled: #{file_path}. Export skipped.")
|
61
|
+
:skip
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def handle_empty_content
|
66
|
+
if content.nil? || content.strip.empty?
|
67
|
+
logger.skipped("Export content is empty. Export skipped.")
|
68
|
+
:skip
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def file_path
|
73
|
+
format = export_config[:format]
|
74
|
+
path = export_config[:path]
|
75
|
+
|
76
|
+
"#{path}/trace_output.#{format}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def write_file(data)
|
80
|
+
File.write(file_path, data)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base_formatter"
|
4
|
+
|
5
|
+
module TraceViz
|
6
|
+
module Exporters
|
7
|
+
module Formatters
|
8
|
+
class MethodCallFormatter < BaseFormatter
|
9
|
+
def format
|
10
|
+
[
|
11
|
+
indent_representation,
|
12
|
+
depth_representation,
|
13
|
+
method_name_representation,
|
14
|
+
source_location_representation,
|
15
|
+
params_representation,
|
16
|
+
].compact.join(" ")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base_formatter"
|
4
|
+
|
5
|
+
module TraceViz
|
6
|
+
module Exporters
|
7
|
+
module Formatters
|
8
|
+
class MethodReturnFormatter < BaseFormatter
|
9
|
+
def format
|
10
|
+
[
|
11
|
+
indent_representation,
|
12
|
+
depth_representation,
|
13
|
+
method_name_representation,
|
14
|
+
result_representation,
|
15
|
+
source_location_representation,
|
16
|
+
execution_time_representation,
|
17
|
+
].compact.join(" ")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|