trace_viz 0.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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +15 -0
- data/.tool-versions +1 -0
- data/.vscode/launch.json +32 -0
- data/.vscode/settings.json +33 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +167 -0
- data/Rakefile +12 -0
- data/examples/example.rb +42 -0
- data/lib/trace_viz/adapters/base_adapter.rb +13 -0
- data/lib/trace_viz/adapters/trace_point/depth_manager.rb +34 -0
- data/lib/trace_viz/adapters/trace_point/event_handler.rb +36 -0
- data/lib/trace_viz/adapters/trace_point/trace_data.rb +89 -0
- data/lib/trace_viz/adapters/trace_point/trace_formatter.rb +95 -0
- data/lib/trace_viz/adapters/trace_point/trace_logger.rb +44 -0
- data/lib/trace_viz/adapters/trace_point_adapter.rb +25 -0
- data/lib/trace_viz/configuration.rb +61 -0
- data/lib/trace_viz/context/base_context.rb +13 -0
- data/lib/trace_viz/context/config_context.rb +34 -0
- data/lib/trace_viz/context/manager/context_map.rb +31 -0
- data/lib/trace_viz/context/manager/context_operations.rb +60 -0
- data/lib/trace_viz/context/manager/context_registry.rb +20 -0
- data/lib/trace_viz/context/manager/context_validation.rb +34 -0
- data/lib/trace_viz/context/manager.rb +37 -0
- data/lib/trace_viz/context/tracking/depth.rb +31 -0
- data/lib/trace_viz/context/tracking_context.rb +18 -0
- data/lib/trace_viz/context.rb +13 -0
- data/lib/trace_viz/core/tracer.rb +19 -0
- data/lib/trace_viz/core.rb +8 -0
- data/lib/trace_viz/errors.rb +8 -0
- data/lib/trace_viz/logger.rb +73 -0
- data/lib/trace_viz/utils/colorize.rb +35 -0
- data/lib/trace_viz/version.rb +5 -0
- data/lib/trace_viz.rb +13 -0
- data/sig/trace_viz.rbs +4 -0
- metadata +83 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "trace_viz/utils/colorize"
|
4
|
+
|
5
|
+
module TraceViz
|
6
|
+
module Adapters
|
7
|
+
module TracePoint
|
8
|
+
class TraceFormatter
|
9
|
+
def initialize(trace_data)
|
10
|
+
@trace_data = trace_data
|
11
|
+
@config = @trace_data.config
|
12
|
+
@logger = TraceViz.logger
|
13
|
+
end
|
14
|
+
|
15
|
+
def format_call
|
16
|
+
return "" if trace_data.exceeded_max_depth?
|
17
|
+
|
18
|
+
[
|
19
|
+
indent_if_enabled,
|
20
|
+
colorize(depth_if_enabled, :blue),
|
21
|
+
colorize(method_name_if_enabled, :light_green),
|
22
|
+
colorize(source_location_if_enabled, :dark_gray),
|
23
|
+
colorize(params_if_enabled, :yellow),
|
24
|
+
].compact.join(" ")
|
25
|
+
end
|
26
|
+
|
27
|
+
def format_return
|
28
|
+
return "" if trace_data.exceeded_max_depth?
|
29
|
+
|
30
|
+
[
|
31
|
+
indent_if_enabled,
|
32
|
+
colorize(depth_if_enabled, :blue),
|
33
|
+
colorize(method_name_if_enabled, :light_green),
|
34
|
+
colorize(result_if_enabled, :cyan),
|
35
|
+
colorize(source_location_if_enabled, :dark_gray),
|
36
|
+
colorize(execution_time_if_enabled, :red),
|
37
|
+
].compact.join(" ")
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_reader :trace_data, :config, :logger
|
43
|
+
|
44
|
+
def indent_if_enabled
|
45
|
+
return unless config.show_indent && config.show_depth
|
46
|
+
|
47
|
+
" " * (config.tab_size * trace_data.depth)
|
48
|
+
end
|
49
|
+
|
50
|
+
def depth_if_enabled
|
51
|
+
return unless config.show_depth
|
52
|
+
|
53
|
+
"#depth:#{trace_data.depth}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def method_name_if_enabled
|
57
|
+
return unless config.show_method_name
|
58
|
+
|
59
|
+
"#{trace_data.klass}##{trace_data.id}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def source_location_if_enabled
|
63
|
+
return unless config.show_source_location
|
64
|
+
|
65
|
+
"at #{trace_data.path}:#{trace_data.line_number}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def params_if_enabled
|
69
|
+
return unless config.show_params
|
70
|
+
|
71
|
+
param_values = trace_data.params.map do |var|
|
72
|
+
trace_data.trace_point.binding.local_variable_get(var).inspect
|
73
|
+
end.join(", ")
|
74
|
+
"(#{param_values})"
|
75
|
+
end
|
76
|
+
|
77
|
+
def result_if_enabled
|
78
|
+
return unless config.show_return_value
|
79
|
+
|
80
|
+
"#=> #{trace_data.result.inspect}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def execution_time_if_enabled
|
84
|
+
return unless config.show_execution_time && trace_data.duration
|
85
|
+
|
86
|
+
"in #{trace_data.duration}ms"
|
87
|
+
end
|
88
|
+
|
89
|
+
def colorize(text, color_key)
|
90
|
+
Utils::Colorize.colorize(text, color_key)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TraceViz
|
4
|
+
module Adapters
|
5
|
+
module TracePoint
|
6
|
+
class TraceLogger
|
7
|
+
def initialize(trace_data)
|
8
|
+
@trace_data = trace_data
|
9
|
+
@config = @trace_data.config
|
10
|
+
@formatter = TraceFormatter.new(@trace_data)
|
11
|
+
end
|
12
|
+
|
13
|
+
def log_trace
|
14
|
+
return unless should_log?
|
15
|
+
|
16
|
+
case trace_data.event
|
17
|
+
when :call
|
18
|
+
log_call
|
19
|
+
when :return
|
20
|
+
log_return
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :trace_data, :config, :formatter
|
27
|
+
|
28
|
+
def log_call
|
29
|
+
formatted_call = formatter.format_call
|
30
|
+
TraceViz.logger.start(formatted_call)
|
31
|
+
end
|
32
|
+
|
33
|
+
def log_return
|
34
|
+
formatted_return = formatter.format_return
|
35
|
+
TraceViz.logger.finish(formatted_return)
|
36
|
+
end
|
37
|
+
|
38
|
+
def should_log?
|
39
|
+
config.show_trace_events.include?(trace_data.event)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "trace_viz/logger"
|
4
|
+
require "trace_viz/adapters/base_adapter"
|
5
|
+
require "trace_viz/adapters/trace_point/trace_formatter"
|
6
|
+
require "trace_viz/adapters/trace_point/trace_logger"
|
7
|
+
require "trace_viz/adapters/trace_point/trace_data"
|
8
|
+
require "trace_viz/adapters/trace_point/event_handler"
|
9
|
+
|
10
|
+
module TraceViz
|
11
|
+
module Adapters
|
12
|
+
class TracePointAdapter < BaseAdapter
|
13
|
+
def trace(&block)
|
14
|
+
::TracePoint.new(:call, :return) do |tp|
|
15
|
+
trace_data = TracePoint::TraceData.new(tp)
|
16
|
+
|
17
|
+
next if trace_data.internal_call?
|
18
|
+
next if trace_data.exceeded_max_depth?
|
19
|
+
|
20
|
+
TracePoint::EventHandler.new(trace_data).handle
|
21
|
+
end.enable(&block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "trace_viz/logger"
|
4
|
+
|
5
|
+
module TraceViz
|
6
|
+
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
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@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]
|
31
|
+
end
|
32
|
+
|
33
|
+
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
|
41
|
+
end
|
42
|
+
copy.instance_variable_set(var, copy_value)
|
43
|
+
end
|
44
|
+
copy
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class << self
|
49
|
+
def configuration
|
50
|
+
@configuration ||= Configuration.new
|
51
|
+
end
|
52
|
+
|
53
|
+
def configure
|
54
|
+
yield(configuration) if block_given?
|
55
|
+
end
|
56
|
+
|
57
|
+
def logger
|
58
|
+
configuration.logger
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "trace_viz/context/base_context"
|
4
|
+
|
5
|
+
module TraceViz
|
6
|
+
module Context
|
7
|
+
class ConfigContext < BaseContext
|
8
|
+
attr_reader :configuration
|
9
|
+
|
10
|
+
def initialize(**options)
|
11
|
+
super
|
12
|
+
|
13
|
+
@configuration = apply_options(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def temp_configuration
|
17
|
+
@temp_configuration ||= TraceViz.configuration.dup
|
18
|
+
end
|
19
|
+
|
20
|
+
# Apply the overrides from options
|
21
|
+
def apply_options(options)
|
22
|
+
options.each do |key, value|
|
23
|
+
if temp_configuration.respond_to?("#{key}=")
|
24
|
+
temp_configuration.send("#{key}=", value)
|
25
|
+
else
|
26
|
+
warn("TraceViz: Unknown configuration option '#{key}'")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
temp_configuration
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TraceViz
|
4
|
+
module Context
|
5
|
+
class Manager
|
6
|
+
module ContextMap
|
7
|
+
def get_context(key)
|
8
|
+
validate_key!(key)
|
9
|
+
@context_map[key]
|
10
|
+
end
|
11
|
+
|
12
|
+
def clear
|
13
|
+
@context_map.clear
|
14
|
+
end
|
15
|
+
|
16
|
+
def empty?
|
17
|
+
@context_map.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def all_contexts
|
21
|
+
@context_map.map do |key, context|
|
22
|
+
{
|
23
|
+
key: key,
|
24
|
+
context: context,
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "trace_viz/context/base_context"
|
4
|
+
|
5
|
+
module TraceViz
|
6
|
+
module Context
|
7
|
+
class Manager
|
8
|
+
module ContextOperations
|
9
|
+
def create_context(key = nil, **options)
|
10
|
+
if key
|
11
|
+
validate_key!(key)
|
12
|
+
ensure_unique_key!(key)
|
13
|
+
end
|
14
|
+
|
15
|
+
context_class = @registered_contexts[key] || BaseContext
|
16
|
+
context = context_class.new(**options)
|
17
|
+
@context_map[key] = context if key
|
18
|
+
context
|
19
|
+
end
|
20
|
+
|
21
|
+
def enter_context(key = nil, **options)
|
22
|
+
create_context(key, **options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def enter_multiple_contexts(contexts_with_options = {})
|
26
|
+
unless contexts_with_options.is_a?(Hash)
|
27
|
+
raise ContextError, "Expected a Hash of contexts and options, got #{contexts_with_options.class}"
|
28
|
+
end
|
29
|
+
|
30
|
+
contexts_with_options.each do |key, options|
|
31
|
+
enter_context(key, **options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def exit_context(key)
|
36
|
+
validate_key!(key)
|
37
|
+
context = @context_map.delete(key)
|
38
|
+
raise ContextError, "No context found with key '#{key}' to exit" unless context
|
39
|
+
|
40
|
+
context
|
41
|
+
end
|
42
|
+
|
43
|
+
def exit_multiple_contexts(*keys)
|
44
|
+
keys.each do |key|
|
45
|
+
validate_key!(key)
|
46
|
+
exit_context(key)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Execute a block within the context(s) specified
|
51
|
+
def with_contexts(contexts_with_options = {})
|
52
|
+
enter_multiple_contexts(contexts_with_options)
|
53
|
+
yield
|
54
|
+
ensure
|
55
|
+
exit_multiple_contexts(*contexts_with_options.keys)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TraceViz
|
4
|
+
module Context
|
5
|
+
class Manager
|
6
|
+
module ContextRegistry
|
7
|
+
def register_context_type(key, context_class)
|
8
|
+
validate_key!(key)
|
9
|
+
validate_context_class!(context_class)
|
10
|
+
|
11
|
+
if @registered_contexts.key?(key)
|
12
|
+
raise ContextError, "Context type for key '#{key}' is already registered"
|
13
|
+
end
|
14
|
+
|
15
|
+
@registered_contexts[key] = context_class
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TraceViz
|
4
|
+
module Context
|
5
|
+
class Manager
|
6
|
+
module ContextValidation
|
7
|
+
private
|
8
|
+
|
9
|
+
# Validate that the key is either a Symbol or String
|
10
|
+
def validate_key!(key)
|
11
|
+
return unless key
|
12
|
+
|
13
|
+
unless key.is_a?(Symbol) || key.is_a?(String)
|
14
|
+
raise ContextError, "Key must be a Symbol or String, got #{key.class}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Ensure that the key is unique (no existing context with the same key)
|
19
|
+
def ensure_unique_key!(key)
|
20
|
+
if @context_map.key?(key)
|
21
|
+
raise ContextError, "Context with key '#{key}' already exists"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Validate that the context_class inherits from BaseContext
|
26
|
+
def validate_context_class!(context_class)
|
27
|
+
unless context_class < BaseContext
|
28
|
+
raise ContextError, "Context class must inherit from BaseContext"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
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"
|
9
|
+
|
10
|
+
module TraceViz
|
11
|
+
module Context
|
12
|
+
class Manager
|
13
|
+
class << self
|
14
|
+
include ContextMap
|
15
|
+
include ContextValidation
|
16
|
+
include ContextRegistry
|
17
|
+
include ContextOperations
|
18
|
+
|
19
|
+
# Initialize class instance variables
|
20
|
+
def initialize_manager
|
21
|
+
@context_map = {}
|
22
|
+
@registered_contexts = {}
|
23
|
+
|
24
|
+
register_default_contexts
|
25
|
+
end
|
26
|
+
|
27
|
+
def register_default_contexts
|
28
|
+
Manager.register_context_type(:config, ConfigContext)
|
29
|
+
Manager.register_context_type(:tracking, TrackingContext)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Ensure initialization upon loading
|
34
|
+
initialize_manager
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TraceViz
|
4
|
+
module Context
|
5
|
+
module Tracking
|
6
|
+
class Depth
|
7
|
+
attr_reader :current
|
8
|
+
|
9
|
+
def initialize(current = 0)
|
10
|
+
@current = current
|
11
|
+
end
|
12
|
+
|
13
|
+
def increment
|
14
|
+
@current += 1
|
15
|
+
end
|
16
|
+
|
17
|
+
def decrement
|
18
|
+
@current -= 1 if @current.positive?
|
19
|
+
end
|
20
|
+
|
21
|
+
def reset
|
22
|
+
@current = 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def zero?
|
26
|
+
@current.zero?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "trace_viz/context/base_context"
|
4
|
+
require "trace_viz/context/tracking/depth"
|
5
|
+
|
6
|
+
module TraceViz
|
7
|
+
module Context
|
8
|
+
class TrackingContext < BaseContext
|
9
|
+
attr_reader :depth
|
10
|
+
|
11
|
+
def initialize(**options)
|
12
|
+
super
|
13
|
+
|
14
|
+
@depth = Tracking::Depth.new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "trace_viz/logger"
|
4
|
+
require "trace_viz/context"
|
5
|
+
require "trace_viz/configuration"
|
6
|
+
require "trace_viz/adapters/trace_point_adapter"
|
7
|
+
|
8
|
+
module TraceViz
|
9
|
+
module Core
|
10
|
+
class Tracer
|
11
|
+
def trace(**options, &block)
|
12
|
+
Context::Manager.with_contexts(config: options, tracking: {}) do
|
13
|
+
adapter = Adapters::TracePointAdapter.new
|
14
|
+
adapter.trace(&block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TraceViz
|
4
|
+
class Logger
|
5
|
+
COLORS = {
|
6
|
+
reset: "\e[0m",
|
7
|
+
info: "\e[34m",
|
8
|
+
success: "\e[32m",
|
9
|
+
error: "\e[31m",
|
10
|
+
warn: "\e[33m",
|
11
|
+
start: "\e[36m",
|
12
|
+
finish: "\e[35m",
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
EMOJIS = {
|
16
|
+
info: "ℹ️",
|
17
|
+
success: "✅",
|
18
|
+
error: "❌",
|
19
|
+
warn: "⚠️",
|
20
|
+
start: "🚀",
|
21
|
+
finish: "🏁",
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
LEVELS = [:info, :success, :error, :warn, :start, :finish].freeze
|
25
|
+
|
26
|
+
def initialize(output: $stdout)
|
27
|
+
@output = output
|
28
|
+
end
|
29
|
+
|
30
|
+
def info(message)
|
31
|
+
log(:info, message)
|
32
|
+
end
|
33
|
+
|
34
|
+
def success(message)
|
35
|
+
log(:success, message)
|
36
|
+
end
|
37
|
+
|
38
|
+
def error(message)
|
39
|
+
log(:error, message)
|
40
|
+
end
|
41
|
+
|
42
|
+
def warn(message)
|
43
|
+
log(:warn, message)
|
44
|
+
end
|
45
|
+
|
46
|
+
def start(message)
|
47
|
+
log(:start, message)
|
48
|
+
end
|
49
|
+
|
50
|
+
def finish(message)
|
51
|
+
log(:finish, message)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def log(level, message)
|
57
|
+
return unless LEVELS.include?(level)
|
58
|
+
|
59
|
+
color = COLORS[level] || COLORS[:info]
|
60
|
+
emoji = EMOJIS[level] || EMOJIS[:info]
|
61
|
+
|
62
|
+
# Align emoji and level using fixed-width columns
|
63
|
+
formatted_message = format(
|
64
|
+
"#{color}%-3s %-8s#{COLORS[:reset]} %s",
|
65
|
+
emoji,
|
66
|
+
"[#{level.to_s.upcase}]",
|
67
|
+
message,
|
68
|
+
)
|
69
|
+
|
70
|
+
@output.puts(formatted_message)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TraceViz
|
4
|
+
module Utils
|
5
|
+
module Colorize
|
6
|
+
ANSI_COLORS = {
|
7
|
+
reset: "\e[0m",
|
8
|
+
black: "\e[30m",
|
9
|
+
red: "\e[31m",
|
10
|
+
green: "\e[32m",
|
11
|
+
yellow: "\e[33m",
|
12
|
+
blue: "\e[34m",
|
13
|
+
magenta: "\e[35m",
|
14
|
+
cyan: "\e[36m",
|
15
|
+
light_gray: "\e[37m",
|
16
|
+
dark_gray: "\e[90m",
|
17
|
+
light_red: "\e[91m",
|
18
|
+
light_green: "\e[92m",
|
19
|
+
light_yellow: "\e[93m",
|
20
|
+
light_blue: "\e[94m",
|
21
|
+
light_magenta: "\e[95m",
|
22
|
+
light_cyan: "\e[96m",
|
23
|
+
white: "\e[97m",
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def colorize(text, color)
|
28
|
+
return text unless text
|
29
|
+
|
30
|
+
"#{ANSI_COLORS[color]}#{text}#{ANSI_COLORS[:reset]}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/trace_viz.rb
ADDED