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