rsmp 0.35.2 → 0.38.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/.devcontainer/devcontainer.json +22 -0
- data/.github/copilot-instructions.md +33 -0
- data/.github/workflows/copilot-setup-steps.yml +35 -0
- data/.github/workflows/rspec.yaml +2 -1
- data/.github/workflows/rubocop.yaml +17 -0
- data/.gitignore +7 -7
- data/.rubocop.yml +80 -0
- data/Gemfile +13 -1
- data/Gemfile.lock +73 -35
- data/Rakefile +3 -3
- data/bin/console +2 -4
- data/documentation/tasks.md +4 -4
- data/lib/rsmp/cli.rb +147 -124
- data/lib/rsmp/collect/ack_collector.rb +8 -7
- data/lib/rsmp/collect/aggregated_status_collector.rb +4 -4
- data/lib/rsmp/collect/alarm_collector.rb +31 -23
- data/lib/rsmp/collect/alarm_matcher.rb +3 -3
- data/lib/rsmp/collect/collector/logging.rb +17 -0
- data/lib/rsmp/collect/collector/reporting.rb +44 -0
- data/lib/rsmp/collect/collector/status.rb +34 -0
- data/lib/rsmp/collect/collector.rb +69 -150
- data/lib/rsmp/collect/command_matcher.rb +19 -6
- data/lib/rsmp/collect/command_response_collector.rb +7 -7
- data/lib/rsmp/collect/distributor.rb +14 -11
- data/lib/rsmp/collect/filter.rb +31 -15
- data/lib/rsmp/collect/matcher.rb +7 -11
- data/lib/rsmp/collect/queue.rb +4 -4
- data/lib/rsmp/collect/receiver.rb +10 -12
- data/lib/rsmp/collect/state_collector.rb +116 -77
- data/lib/rsmp/collect/status_collector.rb +6 -6
- data/lib/rsmp/collect/status_matcher.rb +17 -7
- data/lib/rsmp/{alarm_state.rb → component/alarm_state.rb} +76 -37
- data/lib/rsmp/{component.rb → component/component.rb} +15 -15
- data/lib/rsmp/component/component_base.rb +89 -0
- data/lib/rsmp/component/component_proxy.rb +75 -0
- data/lib/rsmp/component/components.rb +63 -0
- data/lib/rsmp/convert/export/json_schema.rb +116 -110
- data/lib/rsmp/convert/import/yaml.rb +21 -18
- data/lib/rsmp/{rsmp.rb → helpers/clock.rb} +5 -6
- data/lib/rsmp/{deep_merge.rb → helpers/deep_merge.rb} +2 -1
- data/lib/rsmp/helpers/error.rb +71 -0
- data/lib/rsmp/{inspect.rb → helpers/inspect.rb} +6 -10
- data/lib/rsmp/log/archive.rb +98 -0
- data/lib/rsmp/log/colorization.rb +41 -0
- data/lib/rsmp/log/filtering.rb +54 -0
- data/lib/rsmp/log/logger.rb +206 -0
- data/lib/rsmp/{logging.rb → log/logging.rb} +5 -7
- data/lib/rsmp/message.rb +159 -148
- data/lib/rsmp/{node.rb → node/node.rb} +19 -17
- data/lib/rsmp/node/protocol.rb +37 -0
- data/lib/rsmp/node/site/site.rb +195 -0
- data/lib/rsmp/node/supervisor/modules/configuration.rb +59 -0
- data/lib/rsmp/node/supervisor/modules/connection.rb +140 -0
- data/lib/rsmp/node/supervisor/modules/sites.rb +64 -0
- data/lib/rsmp/node/supervisor/supervisor.rb +72 -0
- data/lib/rsmp/{task.rb → node/task.rb} +29 -19
- data/lib/rsmp/proxy/modules/acknowledgements.rb +144 -0
- data/lib/rsmp/proxy/modules/receive.rb +119 -0
- data/lib/rsmp/proxy/modules/send.rb +76 -0
- data/lib/rsmp/proxy/modules/state.rb +25 -0
- data/lib/rsmp/proxy/modules/tasks.rb +105 -0
- data/lib/rsmp/proxy/modules/versions.rb +69 -0
- data/lib/rsmp/proxy/modules/watchdogs.rb +66 -0
- data/lib/rsmp/proxy/proxy.rb +199 -0
- data/lib/rsmp/proxy/site/modules/aggregated_status.rb +52 -0
- data/lib/rsmp/proxy/site/modules/alarms.rb +27 -0
- data/lib/rsmp/proxy/site/modules/commands.rb +31 -0
- data/lib/rsmp/proxy/site/modules/status.rb +110 -0
- data/lib/rsmp/proxy/site/site_proxy.rb +205 -0
- data/lib/rsmp/proxy/supervisor/modules/aggregated_status.rb +47 -0
- data/lib/rsmp/proxy/supervisor/modules/alarms.rb +73 -0
- data/lib/rsmp/proxy/supervisor/modules/commands.rb +53 -0
- data/lib/rsmp/proxy/supervisor/modules/status.rb +204 -0
- data/lib/rsmp/proxy/supervisor/supervisor_proxy.rb +178 -0
- data/lib/rsmp/tlc/detector_logic.rb +18 -34
- data/lib/rsmp/tlc/input_states.rb +126 -0
- data/lib/rsmp/tlc/modules/detector_logics.rb +50 -0
- data/lib/rsmp/tlc/modules/display.rb +78 -0
- data/lib/rsmp/tlc/modules/helpers.rb +41 -0
- data/lib/rsmp/tlc/modules/inputs.rb +173 -0
- data/lib/rsmp/tlc/modules/modes.rb +253 -0
- data/lib/rsmp/tlc/modules/outputs.rb +30 -0
- data/lib/rsmp/tlc/modules/plans.rb +218 -0
- data/lib/rsmp/tlc/modules/signal_groups.rb +109 -0
- data/lib/rsmp/tlc/modules/startup_sequence.rb +22 -0
- data/lib/rsmp/tlc/modules/system.rb +140 -0
- data/lib/rsmp/tlc/modules/traffic_data.rb +49 -0
- data/lib/rsmp/tlc/signal_group.rb +37 -41
- data/lib/rsmp/tlc/signal_plan.rb +14 -11
- data/lib/rsmp/tlc/signal_priority.rb +39 -35
- data/lib/rsmp/tlc/startup_sequence.rb +59 -0
- data/lib/rsmp/tlc/traffic_controller.rb +39 -1006
- data/lib/rsmp/tlc/traffic_controller_site.rb +58 -57
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +86 -49
- data/rsmp.gemspec +24 -30
- metadata +87 -130
- data/lib/rsmp/archive.rb +0 -76
- data/lib/rsmp/collect/message_matchers.rb +0 -0
- data/lib/rsmp/component_base.rb +0 -87
- data/lib/rsmp/component_proxy.rb +0 -57
- data/lib/rsmp/components.rb +0 -65
- data/lib/rsmp/error.rb +0 -71
- data/lib/rsmp/logger.rb +0 -216
- data/lib/rsmp/proxy.rb +0 -695
- data/lib/rsmp/site.rb +0 -188
- data/lib/rsmp/site_proxy.rb +0 -389
- data/lib/rsmp/supervisor.rb +0 -287
- data/lib/rsmp/supervisor_proxy.rb +0 -516
- data/lib/rsmp/tlc/inputs.rb +0 -134
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Error < StandardError
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
class InvalidPacket < Error
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class MalformedMessage < Error
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class SchemaError < Error
|
|
12
|
+
attr_accessor :schemas
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class InvalidMessage < Error
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class UnknownMessage < Error
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class MissingAcknowledgment < Error
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class MissingWatchdog < Error
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class MessageRejected < Error
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class MissingAttribute < InvalidMessage
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class FatalError < Error
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class HandshakeError < FatalError
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class NotReady < Error
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class TimeoutError < Error
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class DisconnectError < Error
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class ConnectionError < Error
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class UnknownComponent < Error
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class UnknownCommand < Error
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class UnknownStatus < Error
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class ConfigurationError < Error
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class RepeatedAlarmError < Error
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class RepeatedStatusError < Error
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
class TimestampError < Error
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -12,23 +12,20 @@
|
|
|
12
12
|
|
|
13
13
|
module RSMP
|
|
14
14
|
module Inspect
|
|
15
|
-
|
|
16
15
|
def inspector *short_items
|
|
17
16
|
instance_variables.map do |var_name|
|
|
18
17
|
var = instance_variable_get(var_name)
|
|
19
18
|
class_name = var.class.name
|
|
20
19
|
|
|
21
20
|
short = short_items.include?(var_name) ||
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
class_name.start_with?('Async') ||
|
|
22
|
+
class_name.start_with?('RSMP')
|
|
24
23
|
|
|
25
24
|
if short
|
|
26
|
-
if var.is_a?
|
|
27
|
-
"#{var_name}: #<#{class_name}:#{class_name.object_id}, #{var.size} items>"
|
|
28
|
-
elsif var.is_a? Hash
|
|
25
|
+
if var.is_a?(Array) || var.is_a?(Hash)
|
|
29
26
|
"#{var_name}: #<#{class_name}:#{class_name.object_id}, #{var.size} items>"
|
|
30
27
|
else
|
|
31
|
-
"#{var_name}: #{var
|
|
28
|
+
"#{var_name}: #{var}"
|
|
32
29
|
end
|
|
33
30
|
else
|
|
34
31
|
"#{var_name}: #{var.inspect}"
|
|
@@ -39,8 +36,7 @@ module RSMP
|
|
|
39
36
|
# override this if you want additional variable to be shown in the short format,
|
|
40
37
|
# or ottherwise change the inspect format
|
|
41
38
|
def inspect
|
|
42
|
-
"#<#{self.class.name}:#{
|
|
39
|
+
"#<#{self.class.name}:#{object_id}, #{inspector}>"
|
|
43
40
|
end
|
|
44
|
-
|
|
45
41
|
end
|
|
46
|
-
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Archive of log items, which can be messages or info items.
|
|
2
|
+
# All items are timestamped, and stored chronologically.
|
|
3
|
+
|
|
4
|
+
module RSMP
|
|
5
|
+
class Archive
|
|
6
|
+
include Inspect
|
|
7
|
+
|
|
8
|
+
attr_reader :items
|
|
9
|
+
|
|
10
|
+
@index = 0
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_accessor :index
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(max = 100)
|
|
17
|
+
@items = []
|
|
18
|
+
@max = max
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def inspect
|
|
22
|
+
"#<#{self.class.name}:#{object_id}, #{inspector(:@items)}>"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.prepare_item(item)
|
|
26
|
+
raise ArgumentError unless item.is_a? Hash
|
|
27
|
+
|
|
28
|
+
cleaned = item.slice(:author, :level, :ip, :port, :site_id, :component, :text, :message, :exception)
|
|
29
|
+
cleaned[:timestamp] = Clock.now
|
|
30
|
+
if item[:message]
|
|
31
|
+
cleaned[:direction] = item[:message].direction
|
|
32
|
+
cleaned[:component] = item[:message].attributes['cId']
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
cleaned
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.increase_index
|
|
39
|
+
self.index += 1
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.current_index
|
|
43
|
+
index
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def by_level(levels)
|
|
47
|
+
items.select { |item| levels.include? item[:level] }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def strings
|
|
51
|
+
items.map { |item| item[:str] }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def add(item)
|
|
55
|
+
item[:index] = RSMP::Archive.increase_index
|
|
56
|
+
@items << item
|
|
57
|
+
return unless @items.size > @max
|
|
58
|
+
|
|
59
|
+
@items.shift
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def find(options, &)
|
|
65
|
+
# search backwards from newest to older, stopping once messages
|
|
66
|
+
# are older that options[:earliest]
|
|
67
|
+
out = []
|
|
68
|
+
@items.reverse_each do |item|
|
|
69
|
+
break if too_old?(item, options[:earliest])
|
|
70
|
+
next unless matches_filters?(item, options, &)
|
|
71
|
+
|
|
72
|
+
out.unshift item
|
|
73
|
+
end
|
|
74
|
+
out
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def too_old?(item, earliest)
|
|
78
|
+
earliest && item[:timestamp] < earliest
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def matches_filters?(item, options, &block)
|
|
82
|
+
return false if options[:level] && item[:level] != options[:level]
|
|
83
|
+
return false if options[:type] && !matches_type?(item, options[:type])
|
|
84
|
+
return false if options[:with_message] && !message?(item)
|
|
85
|
+
return false if block_given? && block.call != true
|
|
86
|
+
|
|
87
|
+
true
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def matches_type?(item, type)
|
|
91
|
+
item[:message] && item[:message].type == type
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def message?(item)
|
|
95
|
+
item[:direction] && item[:message]
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Logger
|
|
3
|
+
# Handles colorization of log output
|
|
4
|
+
module Colorization
|
|
5
|
+
def default_colors
|
|
6
|
+
{
|
|
7
|
+
'info' => 'white',
|
|
8
|
+
'log' => 'light_blue',
|
|
9
|
+
'statistics' => 'light_black',
|
|
10
|
+
'warning' => 'light_yellow',
|
|
11
|
+
'error' => 'red',
|
|
12
|
+
'debug' => 'light_black',
|
|
13
|
+
'collect' => 'light_black'
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def colorize_with_map(level, str, colors)
|
|
18
|
+
color = colors[level.to_s]
|
|
19
|
+
color ? str.colorize(color.to_sym) : str
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def apply_hash_colors(level, str)
|
|
23
|
+
colors = default_colors
|
|
24
|
+
colors.merge! @settings['color'] if @settings['color'].is_a?(Hash)
|
|
25
|
+
colorize_with_map(level, str, colors)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def colorize(level, str)
|
|
29
|
+
return str if @settings['color'] == false || @settings['color'].nil?
|
|
30
|
+
|
|
31
|
+
if @settings['color'] == true || @settings['color'].is_a?(Hash)
|
|
32
|
+
apply_hash_colors(level, str)
|
|
33
|
+
elsif %i[nack warning error].include?(level)
|
|
34
|
+
str.colorize(@settings['color']).bold
|
|
35
|
+
else
|
|
36
|
+
str.colorize @settings['color']
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Logger
|
|
3
|
+
# Handles filtering logic for log output
|
|
4
|
+
module Filtering
|
|
5
|
+
def level_enabled?(item)
|
|
6
|
+
return false if @settings['info'] == false && item[:level] == :info
|
|
7
|
+
return false if @settings['debug'] != true && item[:level] == :debug
|
|
8
|
+
return false if @settings['statistics'] != true && item[:level] == :statistics
|
|
9
|
+
return false if @settings['test'] != true && item[:level] == :test
|
|
10
|
+
|
|
11
|
+
true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def message_ignored?(item)
|
|
15
|
+
return false unless item[:message]
|
|
16
|
+
|
|
17
|
+
type = item[:message].type
|
|
18
|
+
ack = %w[MessageAck MessageNotAck].include?(type)
|
|
19
|
+
return true unless ignorable?(type, ack, item)
|
|
20
|
+
return true unless acknowledgement_enabled?(ack, item)
|
|
21
|
+
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ignorable?(type, ack, item)
|
|
26
|
+
@ignorable.each_pair do |key, types|
|
|
27
|
+
ignore = [types].flatten
|
|
28
|
+
next unless @settings[key] == false
|
|
29
|
+
return false if ignore.include?(type)
|
|
30
|
+
|
|
31
|
+
return false if ack && item[:message].original && ignore.include?(item[:message].original.type)
|
|
32
|
+
end
|
|
33
|
+
true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def acknowledgement_enabled?(ack, item)
|
|
37
|
+
return true unless ack
|
|
38
|
+
return true if @settings['acknowledgements'] != false
|
|
39
|
+
return true if %i[not_acknowledged warning error].include?(item[:level])
|
|
40
|
+
|
|
41
|
+
false
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def output?(item, force: false)
|
|
45
|
+
return false if muted?(item)
|
|
46
|
+
return false if @settings['active'] == false && force != true
|
|
47
|
+
return false unless level_enabled?(item)
|
|
48
|
+
return false if message_ignored?(item)
|
|
49
|
+
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Logger
|
|
3
|
+
include Filtering
|
|
4
|
+
include Colorization
|
|
5
|
+
|
|
6
|
+
attr_accessor :settings
|
|
7
|
+
|
|
8
|
+
def default_output_settings
|
|
9
|
+
{
|
|
10
|
+
'active' => true,
|
|
11
|
+
'path' => nil,
|
|
12
|
+
'stream' => nil,
|
|
13
|
+
'color' => true,
|
|
14
|
+
'debug' => false,
|
|
15
|
+
'statistics' => false,
|
|
16
|
+
'hide_ip_and_port' => false,
|
|
17
|
+
'acknowledgements' => false,
|
|
18
|
+
'watchdogs' => false,
|
|
19
|
+
'alarms' => true,
|
|
20
|
+
'json' => false,
|
|
21
|
+
'tabs' => '-'
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def default_field_settings
|
|
26
|
+
{
|
|
27
|
+
'prefix' => false,
|
|
28
|
+
'index' => false,
|
|
29
|
+
'author' => false,
|
|
30
|
+
'timestamp' => true,
|
|
31
|
+
'ip' => false,
|
|
32
|
+
'port' => false,
|
|
33
|
+
'site_id' => true,
|
|
34
|
+
'component' => true,
|
|
35
|
+
'direction' => false,
|
|
36
|
+
'level' => false,
|
|
37
|
+
'id' => true,
|
|
38
|
+
'text' => true
|
|
39
|
+
}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def default_logger_settings
|
|
43
|
+
default_output_settings.merge(default_field_settings)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def default_field_lengths
|
|
47
|
+
{
|
|
48
|
+
'index' => 7,
|
|
49
|
+
'author' => 13,
|
|
50
|
+
'timestamp' => 24,
|
|
51
|
+
'ip' => 22,
|
|
52
|
+
'port' => 5,
|
|
53
|
+
'site_id' => 19,
|
|
54
|
+
'component' => 19,
|
|
55
|
+
'direction' => 3,
|
|
56
|
+
'level' => 7,
|
|
57
|
+
'id' => 4
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def ignorable_messages
|
|
62
|
+
{
|
|
63
|
+
'versions' => ['Version'],
|
|
64
|
+
'statuses' => %w[StatusRequest StatusSubscribe StatusUnsubscribe StatusResponse StatusUpdate],
|
|
65
|
+
'commands' => %w[CommandRequest CommandResponse],
|
|
66
|
+
'watchdogs' => 'Watchdog',
|
|
67
|
+
'alarms' => ['Alarm'],
|
|
68
|
+
'aggregated_status' => %w[AggregatedStatus AggregatedStatusRequest]
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def apply_default_lengths(settings)
|
|
73
|
+
lengths = default_field_lengths
|
|
74
|
+
settings.to_h do |key, value|
|
|
75
|
+
if value == true && lengths[key]
|
|
76
|
+
[key, lengths[key]]
|
|
77
|
+
else
|
|
78
|
+
[key, value]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def initialize(settings = {})
|
|
84
|
+
@ignorable = ignorable_messages
|
|
85
|
+
@settings = settings ? default_logger_settings.merge(settings) : default_logger_settings
|
|
86
|
+
@settings = apply_default_lengths(@settings)
|
|
87
|
+
@muted = {}
|
|
88
|
+
setup_output_destination
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def setup_output_destination
|
|
92
|
+
@stream = if @settings['stream']
|
|
93
|
+
@settings['stream']
|
|
94
|
+
elsif @settings['path']
|
|
95
|
+
File.open(@settings['path'], 'a') # appending
|
|
96
|
+
else
|
|
97
|
+
$stdout
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def mute(ip, port)
|
|
102
|
+
@muted["#{ip}:#{port}"] = true
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def unmute(ip, port)
|
|
106
|
+
@muted.delete "#{ip}:#{port}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def unmute_all
|
|
110
|
+
@muted = {}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def muted?(item)
|
|
114
|
+
item[:ip] && item[:port] && @muted["#{item[:ip]}:#{item[:port]}"]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def level_enabled?(item)
|
|
118
|
+
return false if @settings['info'] == false && item[:level] == :info
|
|
119
|
+
return false if @settings['debug'] != true && item[:level] == :debug
|
|
120
|
+
return false if @settings['statistics'] != true && item[:level] == :statistics
|
|
121
|
+
return false if @settings['test'] != true && item[:level] == :test
|
|
122
|
+
|
|
123
|
+
true
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def output(level, str)
|
|
127
|
+
return if str.empty? || /^\s+$/.match(str)
|
|
128
|
+
|
|
129
|
+
str = colorize level, str
|
|
130
|
+
@stream.puts str
|
|
131
|
+
@stream.flush
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def log(item, force: false)
|
|
135
|
+
return unless output?(item, force: force)
|
|
136
|
+
|
|
137
|
+
output item[:level], build_output(item)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def self.shorten_message_id(m_id, length = 4)
|
|
141
|
+
if m_id
|
|
142
|
+
m_id[0..(length - 1)].ljust(length)
|
|
143
|
+
else
|
|
144
|
+
' ' * length
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def dump(archive, num: nil)
|
|
149
|
+
num ||= archive.items.size
|
|
150
|
+
log = archive.items.last(num).map do |item|
|
|
151
|
+
str = build_output item
|
|
152
|
+
colorize item[:level], str
|
|
153
|
+
end
|
|
154
|
+
log.join("\n")
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def build_part(parts, item, key, &block)
|
|
158
|
+
skey = key.to_s
|
|
159
|
+
return unless @settings[skey]
|
|
160
|
+
|
|
161
|
+
part = item[key]
|
|
162
|
+
part = yield part if block
|
|
163
|
+
part = part.to_s
|
|
164
|
+
part = part.ljust @settings[skey] if @settings[skey].is_a?(Integer)
|
|
165
|
+
|
|
166
|
+
# replace the first char with a dash if string is all whitespace
|
|
167
|
+
part = @settings['tabs'].ljust(part.length) if @settings['tabs'] && part !~ /\S/
|
|
168
|
+
parts << part
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def add_metadata_parts(parts, item)
|
|
172
|
+
build_part(parts, item, :prefix) { @settings['prefix'] if @settings['prefix'] != false }
|
|
173
|
+
build_part(parts, item, :index)
|
|
174
|
+
build_part(parts, item, :author)
|
|
175
|
+
build_part(parts, item, :timestamp) { |part| Clock.to_s part }
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def add_connection_parts(parts, item)
|
|
179
|
+
build_part(parts, item, :ip)
|
|
180
|
+
build_part(parts, item, :port)
|
|
181
|
+
build_part(parts, item, :site_id)
|
|
182
|
+
build_part(parts, item, :component)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def add_message_parts(parts, item)
|
|
186
|
+
build_part(parts, item, :direction) { |part| { in: 'In', out: 'Out' }[part] }
|
|
187
|
+
build_part(parts, item, :level, &:capitalize)
|
|
188
|
+
build_part(parts, item, :id) { Logger.shorten_message_id(item[:message].m_id, 4) if item[:message] }
|
|
189
|
+
build_part(parts, item, :text)
|
|
190
|
+
build_part(parts, item, :json) { item[:message]&.json }
|
|
191
|
+
build_part(parts, item, :exception) { |e| [e.class, e.backtrace].flatten.join("\n") }
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def add_output_parts(parts, item)
|
|
195
|
+
add_metadata_parts(parts, item)
|
|
196
|
+
add_connection_parts(parts, item)
|
|
197
|
+
add_message_parts(parts, item)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def build_output(item)
|
|
201
|
+
parts = []
|
|
202
|
+
add_output_parts(parts, item)
|
|
203
|
+
parts.join(' ').chomp(@settings['tabs'].to_s).rstrip
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -6,21 +6,19 @@ module RSMP
|
|
|
6
6
|
module Logging
|
|
7
7
|
attr_reader :archive, :logger
|
|
8
8
|
|
|
9
|
-
def initialize_logging
|
|
9
|
+
def initialize_logging(options)
|
|
10
10
|
@archive = options[:archive] || RSMP::Archive.new
|
|
11
11
|
@logger = options[:logger] || RSMP::Logger.new(options[:log_settings])
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def author
|
|
15
|
-
end
|
|
14
|
+
def author; end
|
|
16
15
|
|
|
17
|
-
def log
|
|
18
|
-
default = { text:str, level: :log, author: author, ip: @ip, port: @port }
|
|
16
|
+
def log(str, options = {})
|
|
17
|
+
default = { text: str, level: :log, author: author, ip: @ip, port: @port }
|
|
19
18
|
prepared = RSMP::Archive.prepare_item default.merge(options)
|
|
20
19
|
@archive.add prepared
|
|
21
20
|
@logger.log prepared
|
|
22
21
|
prepared
|
|
23
22
|
end
|
|
24
|
-
|
|
25
23
|
end
|
|
26
|
-
end
|
|
24
|
+
end
|