kanal 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 103821024c6f83e5b37cdbfd488fef5c1b33424604b1d089478b26f585a70f77
4
- data.tar.gz: 05ef0a2d55f73134e7a84613e7f65ceb44c253aa1808e22ea7e5acc1e8907824
3
+ metadata.gz: af8a33084b0e457be1bd9538405b4c885d624d71c67581dc1393474037e9c09b
4
+ data.tar.gz: 2ffae451a04fb4cd5c13079b8bbabcf14b2298fe3bbce681710409fc8da74c5f
5
5
  SHA512:
6
- metadata.gz: 0c04a428a1f6275b06e6b2d9a49bddfa33be0a2f1ca871b4242d26b98b8f01cca563e8c184a587ce84e3961773fb27055a330a6f3dd83c0b9f417452807a1528
7
- data.tar.gz: efc4734c9c5e700b3a35cda943c86b6361e8be1d037d8e2390fe10cb95b24d826fe8f639bc376692eea4c6f77ea34683144b12bbdaaaf332d7497a907467b3b1
6
+ metadata.gz: '0844b50cab451ba9eb5fd2632d2cdab50e8b8260e1a120697a637772be613fbc5cb9504e60c42acf131cc9ad9e84b167e768363b53255bd1b9a4ff172616b9d2'
7
+ data.tar.gz: 3efa7140827918ebc21c954bec87f57bd7dd57d2b3475d8be8ad065660af73cb7d7651cc0d7715f39a07a66accf8f4671707716c98e744eec50bfef9340396e6
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.6.0] 2023-04-24
4
+ - .composite_logger method for core now gives possibility to take that logger and provide it as ruby logger somewhere in the other library (usually to flow some libraries used in your kanal app logs into the kanal logs to have logs in the same place)
5
+ - you can now get beautified router info in string format for debug purpose via router.routes_info_string method
6
+ - better error handling in block specified for .output_ready
7
+ - moved many logs from level INFO level to DEBUG to stop logs overflow of inner machinery when you just want to know some info
8
+
3
9
  ## [0.5.0] 2023-04-14
4
10
  - new router method: `provide_output(output)` for providing output directly to consumer of `.output_ready(&block)` avoiding router and final output hook `:output_before_returned`
5
11
  - new router method: `provide_output_with_input(output, input)` for providing output to consumer of `.output_ready(&block)` avoiding router but applying all hooks attached to the `:output_before_returned` (usually plugins attach to this hook to convert/transform output properties)
data/Gemfile CHANGED
@@ -22,5 +22,6 @@ group :development do
22
22
  end
23
23
 
24
24
  group :test do
25
+ gem "httparty", "0.21.0"
25
26
  gem "simplecov", require: false
26
27
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kanal (0.5.1)
4
+ kanal (0.6.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -12,13 +12,18 @@ GEM
12
12
  diff-lcs (1.5.0)
13
13
  docile (1.4.0)
14
14
  e2mmap (0.1.0)
15
+ httparty (0.21.0)
16
+ mini_mime (>= 1.0.0)
17
+ multi_xml (>= 0.5.2)
15
18
  jaro_winkler (1.5.4)
16
19
  json (2.6.3)
17
20
  kramdown (2.4.0)
18
21
  rexml
19
22
  kramdown-parser-gfm (1.1.0)
20
23
  kramdown (~> 2.0)
24
+ mini_mime (1.1.2)
21
25
  mini_portile2 (2.8.1)
26
+ multi_xml (0.6.0)
22
27
  nokogiri (1.14.3)
23
28
  mini_portile2 (~> 2.8.0)
24
29
  racc (~> 1.4)
@@ -95,6 +100,7 @@ PLATFORMS
95
100
  x86_64-darwin-21
96
101
 
97
102
  DEPENDENCIES
103
+ httparty (= 0.21.0)
98
104
  kanal!
99
105
  rake (~> 13.0)
100
106
  rspec (~> 3.0)
@@ -105,4 +111,4 @@ DEPENDENCIES
105
111
  yard
106
112
 
107
113
  BUNDLED WITH
108
- 2.4.9
114
+ 2.4.5
@@ -17,7 +17,7 @@ module Kanal
17
17
  end
18
18
 
19
19
  def create(&block)
20
- logger.info "Attempting to create condition '#{@name}'"
20
+ logger.debug "Attempting to create condition '#{@name}'"
21
21
 
22
22
  instance_eval(&block)
23
23
 
@@ -33,7 +33,7 @@ module Kanal
33
33
  raise "Please provide met? block for condition #{@name}"
34
34
  end
35
35
 
36
- logger.info "Creating condition '#{@name}'"
36
+ logger.debug "Creating condition '#{@name}'"
37
37
 
38
38
  Condition.new @name, with_argument: @with_argument, &@met_block
39
39
  end
@@ -37,7 +37,7 @@ module Kanal
37
37
  end
38
38
 
39
39
  def register_condition(condition)
40
- logger.info "Attempting to register condition '#{condition.name}'"
40
+ logger.debug "Attempting to register condition '#{condition.name}'"
41
41
 
42
42
  unless condition.is_a? Condition
43
43
  logger.fatal "Attempted to register condition which isn't of Condition class"
@@ -50,7 +50,7 @@ module Kanal
50
50
  return self
51
51
  end
52
52
 
53
- logger.info "Registering condition '#{condition.name}'"
53
+ logger.debug "Registering condition '#{condition.name}'"
54
54
 
55
55
  @conditions.append condition
56
56
 
@@ -34,7 +34,7 @@ module Kanal
34
34
  raise "Please provide conditions for condition pack #{@name}"
35
35
  end
36
36
 
37
- logger.info "Creating condition pack '#{@name}'"
37
+ logger.debug "Creating condition pack '#{@name}'"
38
38
 
39
39
  pack = ConditionPack.new(@name)
40
40
 
@@ -60,7 +60,7 @@ module Kanal
60
60
  raise "Condition pack should be descendant of ConditionPack class"
61
61
  end
62
62
 
63
- logger.info "Registering condition pack '#{pack.name}'"
63
+ logger.debug "Registering condition pack '#{pack.name}'"
64
64
 
65
65
  @condition_packs.append pack
66
66
  end
@@ -67,6 +67,18 @@ module Kanal
67
67
  @services = ServiceContainer.new
68
68
  end
69
69
 
70
+ #
71
+ # This method provides access to composite logger in core.
72
+ # You can use it as a regular logger in your app to feed logs from external libraries into log rotation of Kanal.
73
+ # Example:
74
+ # HTTParty.get 'http://google.com', logger: core.composite_logger
75
+ #
76
+ # @return [Kanal::Core::Logging::CompositeLogger] <description>
77
+ #
78
+ def composite_logger
79
+ logger
80
+ end
81
+
70
82
  #
71
83
  # Method for registering plugins. Plugins should be of type
72
84
  # Kanal::Core::Plugins::Plugin. Meaning that any dervied types
@@ -167,7 +179,7 @@ module Kanal
167
179
  # @return [void] <description>
168
180
  #
169
181
  def register_input_parameter(name, readonly: false)
170
- logger.info "Registering input parameter: '#{name}', readonly: '#{readonly}'"
182
+ logger.debug "Registering input parameter: '#{name}', readonly: '#{readonly}'"
171
183
 
172
184
  @input_parameter_registrator.register_parameter name, readonly: readonly
173
185
  end
@@ -181,7 +193,7 @@ module Kanal
181
193
  # @return [void] <description>
182
194
  #
183
195
  def register_output_parameter(name, readonly: false)
184
- logger.info "Registering output parameter: '#{name}', readonly: '#{readonly}'"
196
+ logger.debug "Registering output parameter: '#{name}', readonly: '#{readonly}'"
185
197
  @output_parameter_registrator.register_parameter name, readonly: readonly
186
198
  end
187
199
 
@@ -196,7 +208,7 @@ module Kanal
196
208
  # @return [void] <description>
197
209
  #
198
210
  def add_condition_pack(name, &block)
199
- logger.info "Starting to create condition pack '#{name}'"
211
+ logger.debug "Starting to create condition pack '#{name}'"
200
212
 
201
213
  creator = ConditionPackCreator.new name
202
214
 
@@ -37,7 +37,7 @@ module Kanal
37
37
  raise "Parameter named #{name} already registered!"
38
38
  end
39
39
 
40
- logger.info "Registering parameter '#{name}'"
40
+ logger.debug "Registering parameter '#{name}'"
41
41
 
42
42
  registration = ParameterRegistration.new readonly
43
43
 
@@ -36,7 +36,7 @@ module Kanal
36
36
  private
37
37
 
38
38
  def construct_output(core)
39
- logger.info "Constructing output for input ##{input.__id__}"
39
+ logger.debug "Constructing output for input ##{input.__id__}"
40
40
 
41
41
  output = Output::Output.new core.output_parameter_registrator, @input, core
42
42
 
@@ -51,20 +51,20 @@ module Kanal
51
51
 
52
52
  error_node = @error_node || @default_error_node
53
53
 
54
- logger.info "Trying to construct error response for input ##{input.__id__}. Error response is default: #{@error_node.nil?}"
54
+ logger.debug "Trying to construct error response for input ##{input.__id__}. Error response is default: #{@error_node.nil?}"
55
55
 
56
56
  begin
57
57
  output.instance_eval(&error_node.response_blocks.first.block)
58
58
  rescue => e
59
59
  logger.error "Failed to construct error response for input ##{input.__id__}. Error: '#{e}'"
60
60
 
61
- logger.info "Trying to construct default error response for input ##{input.__id__}"
61
+ logger.debug "Trying to construct default error response for input ##{input.__id__}"
62
62
 
63
63
  output.instance_eval(&@default_error_node.response_blocks.first.block)
64
64
  end
65
65
  end
66
66
 
67
- logger.info "Output ##{output.__id__} for input ##{input.__id__} constructed"
67
+ logger.debug "Output ##{output.__id__} for input ##{input.__id__} constructed"
68
68
 
69
69
  output
70
70
  end
@@ -38,7 +38,7 @@ module Kanal
38
38
  return
39
39
  end
40
40
 
41
- logger.info "Registering hook '#{name}'"
41
+ logger.debug "Registering hook '#{name}'"
42
42
 
43
43
  @listeners[name] = []
44
44
  end
@@ -67,7 +67,7 @@ module Kanal
67
67
  l.method(:hook_block).call(*args)
68
68
  end
69
69
  rescue RuntimeError => e
70
- raise "There was a problem with calling hooks #{name}. Args: #{args}. More info: #{e}"
70
+ raise "There was a problem with calling hook #{name}. More info: #{e.full_message}"
71
71
  end
72
72
 
73
73
  #
@@ -1,40 +1,68 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "logger"
4
+
3
5
  module Kanal
4
6
  module Core
5
7
  module Logging
6
- class CompositeLogger
8
+ #
9
+ # Object of this class us used to store and use several loggers.
10
+ # It inherits from standard Logger and overrides it's methods for accepting messages for every possible log level.
11
+ # Calling #debug (or any other loglevel) on this object results in calling #debug for every logger that it stores.
12
+ #
13
+ class CompositeLogger < ::Logger
7
14
  # Property allowed_methods defines which methods can be called.
8
15
  # These methods mirror standard Logger methods.
9
16
  def initialize
10
17
  @loggers = []
11
- @allowed_methods = [:debug, :info, :warn, :error, :fatal, :unknown]
12
18
  end
13
19
 
14
20
  def add_logger(logger)
15
21
  @loggers << logger
16
22
  end
17
23
 
18
- # This method gets called when calling any method in @allowed_methods.
19
- # It passes message string to method call of every added logger.
20
- #
21
- # @param method [Symbol]
22
- # @param message [String]
23
- def method_missing(method, message)
24
- # Getting caller class name to put into log message later.
24
+ def debug(message)
25
+ feed_message_to_loggers :debug, caller_class_name(caller.first), message
26
+ end
27
+
28
+ def info(message)
29
+ feed_message_to_loggers :info, caller_class_name(caller.first), message
30
+ end
31
+
32
+ def warn(message)
33
+ feed_message_to_loggers :warn, caller_class_name(caller.first), message
34
+ end
35
+
36
+ def error(message)
37
+ feed_message_to_loggers :error, caller_class_name(caller.first), message
38
+ end
39
+
40
+ def fatal(message)
41
+ feed_message_to_loggers :fatal, caller_class_name(caller.first), message
42
+ end
43
+
44
+ def unknown(message)
45
+ feed_message_to_loggers :unknown, caller_class_name(caller.first), message
46
+ end
47
+
48
+ private
49
+
50
+ def caller_class_name(caller)
25
51
  begin
26
- caller_class_name = "[" + caller[0].split(".rb").first.split("/").last.split('_').collect(&:capitalize).join + "]"
52
+ caller_class_name = "[" + caller.split(".rb").first.split("/").last.split('_').collect(&:capitalize).join + "]"
27
53
  rescue
28
54
  caller_class_name = "[ErrorGettingClassName]"
29
55
  end
30
56
 
31
- raise "Wrong method called for CompositeLogger" unless @allowed_methods.include? method
57
+ caller_class_name
58
+ end
32
59
 
60
+ def feed_message_to_loggers(method_name, caller_class_name, message)
33
61
  @loggers.each do |logger|
34
62
  # progname is a property of standard Logger. It is a prefix for log message.
35
63
  # In our case progname is used to store class name of class which calls for CompositeLogger methods.
36
64
  logger.progname = caller_class_name
37
- logger.send method, message
65
+ logger.send method_name, message
38
66
  end
39
67
  end
40
68
  end
@@ -46,21 +46,21 @@ module Kanal
46
46
  # forward in the workflow: apply hooks in :output_before_ready and pass it to
47
47
  # the end consumer which uses .output_ready(&block)
48
48
  @input_output_pair_queue.hooks.attach :item_queued do |input_output_pair|
49
- _this.logger.info "Calling output_ready block for input ##{input_output_pair.input.__id__} and output #{input_output_pair.output.__id__}. Output body is: '#{input_output_pair.output.body}'"
49
+ _this.logger.debug "Calling output_ready block for input ##{input_output_pair.input.__id__} and output #{input_output_pair.output.__id__}. Output body is: '#{input_output_pair.output.body}'"
50
50
 
51
51
  begin
52
52
  _this.core.hooks.call :output_before_returned, input_output_pair.input, input_output_pair.output
53
53
  rescue => e
54
- logger.error "Error during output_before_returned call: #{e}"
54
+ _this.logger.error "Problem with some hooks inside :output_before_returned. More info: #{e.full_message}"
55
55
  return
56
56
  end
57
57
 
58
58
  begin
59
59
  _this.output_ready_block.call input_output_pair.output
60
60
  _input_output_pair_queue.remove(input_output_pair)
61
- rescue
61
+ rescue => e
62
62
  _input_output_pair_queue.remove(input_output_pair)
63
- raise "Error in output_ready block!"
63
+ _this.logger.error "Problem occurred in block provided in .output_ready(&block), here is more info: #{e.full_message}"
64
64
  end
65
65
  end
66
66
  end
@@ -137,7 +137,7 @@ module Kanal
137
137
 
138
138
  # Main method for creating output(s) if it is found or going to default output
139
139
  def consume_input(input)
140
- logger.info "Consuming input #{input.__id__}."
140
+ logger.debug "Consuming input #{input.__id__}."
141
141
 
142
142
  # Checking if default node with output exists throw error if not
143
143
  unless @default_node
@@ -228,6 +228,19 @@ module Kanal
228
228
  end
229
229
  end
230
230
 
231
+ def routes_info_string
232
+ error_and_default_response_data = "Router Debug Info:
233
+
234
+ Default response: #{variable_defined @default_node}
235
+ Error response: #{variable_defined @error_node}
236
+
237
+ Routes:
238
+ "
239
+ router_data = get_data @root_node
240
+
241
+ error_and_default_response_data + router_data
242
+ end
243
+
231
244
  private :test_input_against_router_node
232
245
 
233
246
  def default_error_response(&block)
@@ -235,6 +248,38 @@ module Kanal
235
248
 
236
249
  @default_error_node.respond(&block)
237
250
  end
251
+
252
+ def get_data(node, depth = 0)
253
+ if node != @root_node
254
+ data = get_node_data_string node
255
+ else
256
+ data = ""
257
+ end
258
+
259
+ if node.children?
260
+ node.children.each do |c|
261
+ c.children? ? symbol = "↳ " : symbol = "⏺ "
262
+
263
+ data = data + (" " * depth) + symbol + get_data(c, depth + 1)
264
+ end
265
+ end
266
+
267
+ data
268
+ end
269
+
270
+ def variable_defined(variable)
271
+ variable.nil? ? "not defined" : "defined"
272
+ end
273
+
274
+ def get_node_data_string(node)
275
+ data = "on :#{node.instance_variable_get(:@condition_pack_name)}, #{node.instance_variable_get(:@condition_name)}: #{node.instance_variable_get(:@condition_argument)}"
276
+
277
+ data = data + ", responses_total: #{node.instance_variable_get(:@response_blocks).count}" if node.instance_variable_get(:@response_blocks).count > 0
278
+
279
+ data = data + "
280
+ "
281
+ data
282
+ end
238
283
  end
239
284
  end
240
285
  end
data/lib/kanal/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kanal
4
- VERSION = "0.5.1"
4
+ VERSION = "0.6.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kanal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - idchlife
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-15 00:00:00.000000000 Z
11
+ date: 2023-04-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Thanks to the core library, ecosystem of Kanal tools can be extendted
14
14
  to use with input-output bot-like behaviour, with routing