pantheios-ruby 0.18.2 → 0.22.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +31 -0
  3. data/README.md +5 -0
  4. data/examples/coloured_console_log_service.rb +37 -0
  5. data/examples/multiple_modules.md +204 -0
  6. data/examples/multiple_modules.rb +132 -0
  7. data/examples/simple_logging.md +65 -0
  8. data/examples/simple_logging.rb +37 -0
  9. data/lib/pantheios/api.rb +21 -5
  10. data/lib/pantheios/application_layer/stock_severity_levels.rb +88 -27
  11. data/lib/pantheios/core.rb +30 -11
  12. data/lib/pantheios/front_ends/threshold_front_end.rb +135 -0
  13. data/lib/pantheios/globals.rb +14 -6
  14. data/lib/pantheios/services.rb +3 -0
  15. data/lib/pantheios/services/coloured_console_log_service.rb +204 -0
  16. data/lib/pantheios/services/common/console.rb +92 -0
  17. data/lib/pantheios/services/multiplexing_log_service.rb +277 -0
  18. data/lib/pantheios/services/null_log_service.rb +4 -3
  19. data/lib/pantheios/services/simple_console_log_service.rb +10 -8
  20. data/lib/pantheios/services/simple_file_log_service.rb +3 -2
  21. data/lib/pantheios/services/standard_log_service_adapter.rb +3 -2
  22. data/lib/pantheios/util/reflection_util.rb +2 -0
  23. data/lib/pantheios/util/thread_util.rb +1 -0
  24. data/lib/pantheios/version.rb +3 -2
  25. data/test/scratch/multiplexing_log_service.rb +109 -0
  26. data/test/unit/application_layer/tc_stock_severity_levels.rb +67 -0
  27. data/test/unit/front_ends/tc_threshold_front_end.rb +102 -0
  28. data/test/unit/front_ends/ts_all.rb +12 -0
  29. data/test/unit/services/tc_multiplexing_log_service.rb +144 -0
  30. data/test/unit/services/tc_simple_console_log_service.rb +3 -3
  31. metadata +24 -7
@@ -5,12 +5,13 @@
5
5
  # Purpose: The Pantheios.Ruby "globals" (::Pantheios::Globals)
6
6
  #
7
7
  # Created: 24th December 2017
8
- # Updated: 4th February 2018
8
+ # Updated: 3rd June 2020
9
9
  #
10
10
  # Home: http://github.com/synesissoftware/Pantheios-Ruby
11
11
  #
12
12
  # Author: Matthew Wilson
13
13
  #
14
+ # Copyright (c) 2019-2020, Matthew Wilson and Synesis Information Systems
14
15
  # Copyright (c) 2017-2018, Matthew Wilson and Synesis Software
15
16
  # All rights reserved.
16
17
  #
@@ -57,6 +58,18 @@ module Pantheios
57
58
  #
58
59
  # === Variables
59
60
  #
61
+ # * *HAS_CASCADED_INCLUDES* [boolean] Determines whether including
62
+ # +::Pantheios+ also includes all relevant parts of subordinate
63
+ # namespaces. See the documentation for the +::Pantheios+ namespace for
64
+ # further details
65
+ #
66
+ # * *INITIAL_SERVICE_CLASSES* [ svc-class, [ svc-class ] ] Specifies
67
+ # the service class(es) that will be used to create the initial service
68
+ # instance. Ignored if INITIAL_SERVICE_INSTANCES specifies an instance
69
+ #
70
+ # * *INITIAL_SERVICE_INSTANCES* [ svc-instance, [ svc-instance ] ] Specifies
71
+ # the initial service instance
72
+ #
60
73
  # * *MAIN_THREAD_NAME* A string specifying the main thread name, or an array
61
74
  # containing a thread instance and a string specifying the thread and its
62
75
  # name
@@ -65,11 +78,6 @@ module Pantheios
65
78
  # form is used then the first initialising thread of Pantheios.Ruby will
66
79
  # be the named thread
67
80
  #
68
- # * *HAS_CASCADED_INCLUDES* [boolean] Determines whether including
69
- # +::Pantheios+ also includes all relevant parts of subordinate
70
- # namespaces. See the documentation for the +::Pantheios+ namespace for
71
- # further details
72
- #
73
81
  # * *PROCESS_NAME* A string specifying the process name, or one of the
74
82
  # recognised symbols - :script, :script_basename, :script_dirname,
75
83
  # :script_realpath, :script_stem - that directs inference of the process
@@ -0,0 +1,3 @@
1
+
2
+ Dir[File.join(File.dirname(__FILE__), 'services', '*log_service.rb')].each { |f| require f }
3
+
@@ -0,0 +1,204 @@
1
+
2
+ # ######################################################################## #
3
+ # File: lib/pantheios/services/coloured_console_log_service.rb
4
+ #
5
+ # Purpose: Definition of the
6
+ # ::Pantheios::Services::ColouredConsoleLogService class
7
+ #
8
+ # Created: 19th June 2019
9
+ # Updated: 4th June 2020
10
+ #
11
+ # Home: http://github.com/synesissoftware/Pantheios-Ruby
12
+ #
13
+ # Author: Matthew Wilson
14
+ #
15
+ # Copyright (c) 2019-2020, Matthew Wilson and Synesis Information Systems
16
+ # Copyright (c) 2019, Matthew Wilson and Synesis Software
17
+ # All rights reserved.
18
+ #
19
+ # Redistribution and use in source and binary forms, with or without
20
+ # modification, are permitted provided that the following conditions are
21
+ # met:
22
+ #
23
+ # * Redistributions of source code must retain the above copyright
24
+ # notice, this list of conditions and the following disclaimer.
25
+ #
26
+ # * Redistributions in binary form must reproduce the above copyright
27
+ # notice, this list of conditions and the following disclaimer in the
28
+ # documentation and/or other materials provided with the distribution.
29
+ #
30
+ # * Neither the names of the copyright holder nor the names of its
31
+ # contributors may be used to endorse or promote products derived from
32
+ # this software without specific prior written permission.
33
+ #
34
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
35
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
36
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
37
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
38
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
40
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
42
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
+ #
46
+ # ######################################################################## #
47
+
48
+
49
+ require 'pantheios/services/common/console'
50
+
51
+ =begin
52
+ =end
53
+
54
+ module Pantheios
55
+ module Services
56
+
57
+ # A class that fulfils the Pantheios *LogService* protocol that allows all
58
+ # severities and logs to the console (via +$stdout+ and +$stderr+)
59
+ #
60
+ # NOTE: The *LogService* protocol is implemented by a class that provides
61
+ # the instance methods +severity_logged?(severity : Object) : boolean+ and
62
+ # +log(severity : Object, t : Time, prefix : String|Array, msg : String)+
63
+ class ColouredConsoleLogService
64
+
65
+ module Constants
66
+
67
+ include ::Pantheios::Services::Common::Console::AnsiEscapeSequences
68
+ end # module Constants
69
+
70
+ def self.requires_prefix?
71
+
72
+ return @requires_prefix unless @requires_prefix.nil?
73
+
74
+ @requires_prefix = ::Pantheios::Services::Common::Console::Internal_::SHOULD_COLOURIZE_ ? :parts : false
75
+ end
76
+
77
+ def requires_prefix?
78
+
79
+ self.class.requires_prefix?
80
+ end
81
+
82
+ def severity_logged? severity
83
+
84
+ true
85
+ end
86
+
87
+ def log sev, t, pref, msg
88
+
89
+ stm = infer_stream sev
90
+
91
+ if requires_prefix?
92
+
93
+ pref = pref.map do |part|
94
+
95
+ bg = Constants::Background
96
+ fg = Constants::Foreground
97
+
98
+ if part.respond_to?(:severity)
99
+
100
+ part = fg.bold part
101
+
102
+ case sev
103
+ when :violation
104
+
105
+ part = bg.red part
106
+ #part = fg.bright_magenta part
107
+ part = fg.bright_yellow part
108
+ part = fg.blinking part
109
+ when :alert
110
+
111
+ part = bg.red part
112
+ part = fg.bright_cyan part
113
+ part = fg.blinking part
114
+ when :critical
115
+
116
+ part = bg.red part
117
+ part = fg.white part
118
+ when :failure
119
+
120
+ part = bg.yellow part
121
+ part = fg.red part
122
+ when :warning
123
+
124
+ part = bg.yellow part
125
+ part = fg.blue part
126
+ when :notice
127
+
128
+ part = bg.dark_grey part
129
+ part = fg.white part
130
+ when :informational
131
+
132
+ part = bg.dark_grey part
133
+ part = fg.light_grey part
134
+ when :debug0
135
+
136
+ part = bg.blue part
137
+ part = fg.light_grey part
138
+ when :debug1
139
+
140
+ part = bg.blue part
141
+ part = fg.light_grey part
142
+ when :debug2
143
+
144
+ part = bg.blue part
145
+ part = fg.light_grey part
146
+ when :debug3
147
+
148
+ part = bg.blue part
149
+ part = fg.light_grey part
150
+ when :debug4
151
+
152
+ part = bg.blue part
153
+ part = fg.light_grey part
154
+ when :debug5
155
+
156
+ part = bg.blue part
157
+ part = fg.light_grey part
158
+ when :trace
159
+
160
+ part = bg.blue part
161
+ part = fg.light_grey part
162
+ when :benchmark
163
+
164
+ part = bg.black part
165
+ part = fg.light_grey part
166
+ else
167
+
168
+ ;
169
+ end
170
+ else
171
+
172
+ part = fg.dark_grey part
173
+ end
174
+
175
+ part
176
+ end.join(', ')
177
+
178
+ pref = '[' + pref + ']: '
179
+
180
+ #pref = pref.map { |pp| pp.severity? ? map_sev_(sev) : sev }.join(
181
+ end
182
+
183
+ stm.puts "#{pref}#{msg}"
184
+ end
185
+
186
+ # Overrideable method that determines which stream to write, based on a
187
+ # severity. This implementation always returns +$stderr+
188
+ #
189
+ # Overrides must return an object that supports the +puts(String)+
190
+ # method
191
+ def infer_stream sev
192
+
193
+ $stderr
194
+ end
195
+
196
+ private
197
+ end # class ColouredConsoleLogService
198
+
199
+ end # module Services
200
+ end # module Pantheios
201
+
202
+ # ############################## end of file ############################# #
203
+
204
+
@@ -0,0 +1,92 @@
1
+
2
+ module Pantheios
3
+ module Services
4
+ module Common
5
+
6
+ module Console
7
+
8
+ module Internal_
9
+
10
+ STDERR_ISATTY_ = $stderr.isatty
11
+ OS_IS_UNIX_ = %w{
12
+
13
+ darwin
14
+ freebsd
15
+ linux
16
+ mingw32
17
+ solaris
18
+ sunos
19
+ }.any? { |os| RUBY_PLATFORM =~ /#{os.downcase}/ }
20
+ SHOULD_COLOURIZE_ = STDERR_ISATTY_ && OS_IS_UNIX_
21
+
22
+ module ColourInitialiser
23
+
24
+ def self.extended other
25
+
26
+ other::COLOURS.each do |name, value|
27
+
28
+ other.const_set(name.to_s.upcase, value)
29
+
30
+ if SHOULD_COLOURIZE_
31
+
32
+ other.define_singleton_method(name) { |s| "\x1B[#{value}m#{s}\x1B[0m" }
33
+ else
34
+
35
+ other.define_singleton_method(name) { |s| s }
36
+ end
37
+ end
38
+ end
39
+ end # module ColourInitialiser
40
+ end # module Internal_
41
+
42
+ module AnsiEscapeSequences
43
+
44
+ module Foreground
45
+
46
+ COLOURS = {
47
+
48
+ blinking: 5,
49
+ bold: 1,
50
+ default: 39,
51
+
52
+ black: 30,
53
+ red: 31,
54
+ green: 32,
55
+ yellow: 33,
56
+ blue: 34,
57
+ magenta: 35,
58
+ cyan: 36,
59
+ light_grey: 37,
60
+
61
+ dark_grey: 90,
62
+ bright_red: 91,
63
+ bright_green: 92,
64
+ bright_yellow: 93,
65
+ bright_blue: 94,
66
+ bright_magenta: 95,
67
+ bright_cyan: 96,
68
+ white: 97,
69
+ }
70
+
71
+ extend Internal_::ColourInitialiser
72
+ end # module Foreground
73
+
74
+ module Background
75
+
76
+ COLOURS = Hash[Foreground::COLOURS.reject { |k, v| [ :blinking, :bold, :default ].include? k }.map { |k, v| [ k, 10 + v ] }]
77
+
78
+ extend Internal_::ColourInitialiser
79
+ end # module Background
80
+
81
+ module Special
82
+
83
+ # TODO
84
+
85
+ end # module Special
86
+ end # end AnsiEscapeSequences
87
+
88
+ end # module Console
89
+ end # module Common
90
+ end # module Services
91
+ end # module Pantheios
92
+
@@ -0,0 +1,277 @@
1
+
2
+ # ######################################################################## #
3
+ # File: lib/pantheios/services/multiplexing_log_service.rb
4
+ #
5
+ # Purpose: Definition of the
6
+ # ::Pantheios::Services::MultiplexingLogService class
7
+ #
8
+ # Created: 14th June 2015
9
+ # Updated: 4th June 2020
10
+ #
11
+ # Home: http://github.com/synesissoftware/Pantheios-Ruby
12
+ #
13
+ # Author: Matthew Wilson
14
+ #
15
+ # Copyright (c) 2019-2020, Matthew Wilson and Synesis Information Systems
16
+ # Copyright (c) 2015-2018, Matthew Wilson and Synesis Software
17
+ # All rights reserved.
18
+ #
19
+ # Redistribution and use in source and binary forms, with or without
20
+ # modification, are permitted provided that the following conditions are
21
+ # met:
22
+ #
23
+ # * Redistributions of source code must retain the above copyright
24
+ # notice, this list of conditions and the following disclaimer.
25
+ #
26
+ # * Redistributions in binary form must reproduce the above copyright
27
+ # notice, this list of conditions and the following disclaimer in the
28
+ # documentation and/or other materials provided with the distribution.
29
+ #
30
+ # * Neither the names of the copyright holder nor the names of its
31
+ # contributors may be used to endorse or promote products derived from
32
+ # this software without specific prior written permission.
33
+ #
34
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
35
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
36
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
37
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
38
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
40
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
42
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
+ #
46
+ # ######################################################################## #
47
+
48
+
49
+ =begin
50
+ =end
51
+
52
+ module Pantheios
53
+ module Services
54
+
55
+ # A class that fulfils the Pantheios *LogService* protocol by multiplexing
56
+ # its responsibilities to a number of (concrete) log service instances
57
+ #
58
+ # NOTE: The *LogService* protocol is implemented by a class that provides
59
+ # the instance methods +severity_logged?(severity : Object) : boolean+ and
60
+ # +log(severity : Object, t : Time, prefix : String|Array, msg : String)+
61
+ class MultiplexingLogService
62
+
63
+ module MultiplexingLogService_Internals_
64
+
65
+ class ServiceManagementInfo
66
+
67
+ def initialize svc
68
+
69
+ @service = svc
70
+ end
71
+
72
+ attr_reader :service
73
+ end
74
+ end
75
+
76
+ # Initializes the instance with an array of log services, according to
77
+ # the given options
78
+ #
79
+ # ===Signature
80
+ #
81
+ # * *Parameters:*
82
+ # - +services+:: [ ::Array ] An array of instances that observe the
83
+ # Log Service protocol
84
+ # - +options+:: [ ::Hash] options
85
+ #
86
+ # * *Options:*
87
+ # - +:level_cache_mode+:: [ ::Symbol ] Specifies the mode of severity
88
+ # level caching, and must be one of the following values:
89
+ # * +:none+:: no severity level caching is performed. This is the
90
+ # default because it is completely thread-safe, but it is the
91
+ # slowest mode, and users are advised to specify another mode
92
+ # suitable to their use
93
+ # * +:thread_fixed+:: remembers the response of each multiplexed log
94
+ # service to each severity level on a thread-specific basis
95
+ # * +:process_fixed+:: remembers the response of each multiplexed
96
+ # log service to each severity level and then remembers that for
97
+ # the duration of the lifetime of the instance
98
+ # - +:unsync_process_lcm+:: [ boolean ] If truey, causes
99
+ # +:process_fixed+ +:level_cache_mode+ to NOT be synchronised; the
100
+ # default is for it to be synchronised using an internal +Mutex+
101
+ # instance
102
+ def initialize services, **options
103
+
104
+ @tss_sym = self.to_s.to_sym
105
+ @services = services.map { |svc| MultiplexingLogService_Internals_::ServiceManagementInfo.new svc }
106
+ @options = options.dup
107
+ @mode = options[:level_cache_mode]
108
+ @unsync_pf = options[:unsync_process_lcm]
109
+
110
+ @process_m = {}
111
+ @mx = Mutex.new unless @unsync_pf
112
+ end
113
+
114
+ private
115
+
116
+ # { svc => { sev => flag } }
117
+ def get_tss_svc_sev_map_
118
+
119
+ sym = @tss_sym
120
+ tc = Thread.current
121
+ m = tc.thread_variable_get sym
122
+
123
+ unless m
124
+
125
+ tc.thread_variable_set sym, (m = {})
126
+ end
127
+
128
+ m
129
+ end
130
+
131
+ def svc_sev_logged_tf_ m, svc, severity
132
+
133
+ m[svc.object_id] ||= {}
134
+
135
+ unless m[svc.object_id].has_key? severity
136
+
137
+ r = svc.severity_logged? severity
138
+
139
+ m[svc.object_id][severity] = r
140
+ else
141
+
142
+ r = m[svc.object_id][severity]
143
+ end
144
+
145
+ r
146
+ end
147
+
148
+ def svc_sev_logged_pf_ m, svc, severity
149
+
150
+ m[svc.object_id] ||= {}
151
+
152
+ unless m[svc.object_id].has_key? severity
153
+
154
+ r = svc.severity_logged? severity
155
+
156
+ m[svc.object_id][severity] = r
157
+ else
158
+
159
+ r = m[svc.object_id][severity]
160
+ end
161
+
162
+ r
163
+ end
164
+
165
+ def sev_logged_pf_ m, severity
166
+
167
+ @services.any? { |smi| svc_sev_logged_pf_ m, smi.service, severity }
168
+ end
169
+ public
170
+
171
+ # Indicates whether any of the services require a prefix and, if so,
172
+ # what it may require
173
+ #
174
+ # === Return
175
+ # (+false+, +true+, +:parts+) An indicator what the most needy of the
176
+ # multiplexed services requires
177
+ def requires_prefix?
178
+
179
+ return @requires_prefix unless @requires_prefix.nil?
180
+
181
+ requires_prefix = false
182
+
183
+ @services.each do |svc|
184
+
185
+ if svc.respond_to? :requires_prefix?
186
+
187
+ case rp = svc.requires_prefix?
188
+ when nil, false
189
+
190
+ ;
191
+ when true
192
+
193
+ requires_prefix ||= true
194
+ when :parts
195
+
196
+ requires_prefix = rp
197
+ break
198
+ else
199
+
200
+ warn "unrecognised return from requires_prefix? for service #{svc}: #{rp} (#{rp.class})"
201
+ end
202
+ end
203
+ end
204
+
205
+ @requires_prefix = requires_prefix
206
+ end
207
+
208
+ # Indicates whether the given severity is to be logged by any of the
209
+ # multiplexed log services
210
+ def severity_logged? severity
211
+
212
+ case @mode
213
+ when :process_fixed
214
+
215
+ if @unsync_pf
216
+
217
+ sev_logged_pf_ @process_m, severity
218
+ else
219
+
220
+ @mx.synchronize { sev_logged_pf_ @process_m, severity }
221
+ end
222
+ when :thread_fixed
223
+
224
+ m = get_tss_svc_sev_map_
225
+
226
+ @services.any? do |smi|
227
+
228
+ svc = smi.service
229
+
230
+ svc_sev_logged_tf_ m, svc, severity
231
+ end
232
+ else # :none
233
+
234
+ @services.any? { |smi| smi.service.severity_logged? severity }
235
+ end
236
+ end
237
+
238
+ def log sev, t, pref, msg
239
+
240
+ tss_m = :thread_fixed == @mode ? get_tss_svc_sev_map_ : nil
241
+
242
+ @services.each do |smi|
243
+
244
+ svc = smi.service
245
+
246
+ case @mode
247
+ when :process_fixed
248
+
249
+ if @unsync_pf
250
+
251
+ isl = svc_sev_logged_pf_ @process_m, svc, sev
252
+ else
253
+
254
+ isl = @mx.synchronize { svc_sev_logged_pf_ @process_m, svc, sev }
255
+ end
256
+ when :thread_fixed
257
+
258
+ m = tss_m
259
+
260
+ isl = svc_sev_logged_tf_ m, svc, sev
261
+ else # :none
262
+
263
+ isl = svc.severity_logged? sev
264
+ end
265
+
266
+
267
+ svc.log sev, t, pref, msg if isl
268
+ end
269
+ end
270
+ end
271
+
272
+ end # module Services
273
+ end # module Pantheios
274
+
275
+ # ############################## end of file ############################# #
276
+
277
+