tochtli 0.5.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 +7 -0
- data/.travis.yml +14 -0
- data/Gemfile +32 -0
- data/History.md +138 -0
- data/README.md +46 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/assets/communication.png +0 -0
- data/assets/layers.png +0 -0
- data/examples/01-screencap-service/Gemfile +3 -0
- data/examples/01-screencap-service/README.md +5 -0
- data/examples/01-screencap-service/client.rb +15 -0
- data/examples/01-screencap-service/common.rb +15 -0
- data/examples/01-screencap-service/server.rb +26 -0
- data/examples/02-log-analyzer/Gemfile +3 -0
- data/examples/02-log-analyzer/README.md +5 -0
- data/examples/02-log-analyzer/client.rb +95 -0
- data/examples/02-log-analyzer/common.rb +33 -0
- data/examples/02-log-analyzer/sample.log +10001 -0
- data/examples/02-log-analyzer/server.rb +133 -0
- data/lib/tochtli.rb +177 -0
- data/lib/tochtli/active_record_connection_cleaner.rb +9 -0
- data/lib/tochtli/application.rb +135 -0
- data/lib/tochtli/base_client.rb +135 -0
- data/lib/tochtli/base_controller.rb +360 -0
- data/lib/tochtli/controller_manager.rb +99 -0
- data/lib/tochtli/engine.rb +15 -0
- data/lib/tochtli/message.rb +114 -0
- data/lib/tochtli/rabbit_client.rb +36 -0
- data/lib/tochtli/rabbit_connection.rb +249 -0
- data/lib/tochtli/reply_queue.rb +129 -0
- data/lib/tochtli/simple_validation.rb +23 -0
- data/lib/tochtli/test.rb +9 -0
- data/lib/tochtli/test/client.rb +28 -0
- data/lib/tochtli/test/controller.rb +66 -0
- data/lib/tochtli/test/integration.rb +78 -0
- data/lib/tochtli/test/memory_cache.rb +22 -0
- data/lib/tochtli/test/test_case.rb +191 -0
- data/lib/tochtli/test/test_unit.rb +22 -0
- data/lib/tochtli/version.rb +3 -0
- data/log_generator.rb +11 -0
- data/test/base_client_test.rb +68 -0
- data/test/controller_functional_test.rb +87 -0
- data/test/controller_integration_test.rb +274 -0
- data/test/controller_manager_test.rb +75 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/config/application.rb +36 -0
- data/test/dummy/config/boot.rb +4 -0
- data/test/dummy/config/database.yml +3 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/rabbit.yml +4 -0
- data/test/dummy/db/.gitkeep +0 -0
- data/test/dummy/log/.gitkeep +0 -0
- data/test/key_matcher_test.rb +100 -0
- data/test/log/.gitkeep +0 -0
- data/test/message_test.rb +80 -0
- data/test/rabbit_client_test.rb +71 -0
- data/test/rabbit_connection_test.rb +151 -0
- data/test/test_helper.rb +32 -0
- data/test/version_test.rb +8 -0
- data/tochtli.gemspec +129 -0
- metadata +259 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 56acd327a8d04ef8de6ca2ab8a2b677e27e276e4
|
4
|
+
data.tar.gz: c0f076e6906b0ef7a401585be0946ec1b8b0d1f3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4653fc71fcd32d2a9a21bb9929d9994564b2b3b5e1a680e04faf414705ad7bf9b9bcc8e12e274d653183f2fec2780adb3d872a93c004123c611820479d95cd97
|
7
|
+
data.tar.gz: 4e799d6d4888f1182772ca63dfdcd534fa2255f50926a98bb2a3df8ba1fd0b5b8b897361227e785dfdb5287269400ecac5cae7be9925f6cd2babf2350889fdb9
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'bunny', '~> 1.7.0'
|
4
|
+
gem 'uber'
|
5
|
+
gem 'virtus'
|
6
|
+
gem 'facets', require: false
|
7
|
+
gem 'hooks'
|
8
|
+
|
9
|
+
group :development do
|
10
|
+
gem 'dalli', '~> 2.6.4'
|
11
|
+
gem 'jeweler', '~> 2.0.1'
|
12
|
+
|
13
|
+
gem 'mini_cache'
|
14
|
+
gem 'yard', '~> 0.8'
|
15
|
+
|
16
|
+
if ENV['RAILS_VER']
|
17
|
+
gem 'sqlite3'
|
18
|
+
rails_ver = ENV['RAILS_VER'] # Setup rails version for tests
|
19
|
+
gem 'rails', rails_ver
|
20
|
+
if rails_ver.to_i < 4
|
21
|
+
gem 'test-unit', '>= 3.0.9'
|
22
|
+
end
|
23
|
+
gem 'tzinfo-data' if RUBY_PLATFORM =~ /mswin|mingw/ && rails_ver >= '4.0' # require tzinfo-data only for Rails 4 on windows
|
24
|
+
gem 'minitest', rails_ver < '4.0' ? '~> 4.7.5' : '~> 5.4.2'
|
25
|
+
gem 'minitest-rails', rails_ver < '4.0' ? '~> 1.0.1' : '~> 2.1.1'
|
26
|
+
else
|
27
|
+
#gem 'rails', '>= 3.2.15'
|
28
|
+
gem 'minitest', '>= 4.7.5'
|
29
|
+
gem 'minitest-reporters', '>= 0.5.0'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
data/History.md
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
## 0.5.0 / 2015-08-19
|
2
|
+
|
3
|
+
* Usage examples
|
4
|
+
* Key pattern support for a controller routing (ex. on Message, :action, routing_key: 'my.key.*')
|
5
|
+
* Tochtli::BaseController#rabbit_connection delegation
|
6
|
+
* Tochtli::BaseController callbacks: (before|after)_(setup|start|stop|restart) with `hooks` gem
|
7
|
+
* Tochtli::BaseController#restart supports multiple queues
|
8
|
+
* Tochtli::Message#routing_key as a block
|
9
|
+
* Default Tochtli.logger logs on STDERR with WARN level
|
10
|
+
* Tochtli.cache is not obligatory
|
11
|
+
* Get rid of Tochtli::Test cases - replace with concerns (ex. include Tochtli::Test::Client not inherit from)
|
12
|
+
|
13
|
+
## 0.4.0 / 2015-07-10
|
14
|
+
|
15
|
+
* Remove ActiveSupport dependencies (use Facets if Rails not loaded)
|
16
|
+
* Replace ActiveSupport::Cache with MiniCache and fix validation tests
|
17
|
+
* Use RabbitConnection#on_return method with all exchanges
|
18
|
+
* YARD introduced
|
19
|
+
* Tochtli::SimpleValidation for validation error messages
|
20
|
+
* RabbitClient#rabbit_config removed
|
21
|
+
* Removed RabbitClient#publish_and_wait (use SyncMessageHandler
|
22
|
+
* Fix #2: Client error on dropped message
|
23
|
+
* No more automatic routing. All routes have to be defined in the controller. (got rid of the MessageMap)
|
24
|
+
* Message attributes rewritten with Virtus.
|
25
|
+
* Message#bind_topic renamed to route_to
|
26
|
+
* BaseController#subscribe renamed to bind
|
27
|
+
* BaseClient#instance (singleton support) removed
|
28
|
+
* Tochtli::Test::IntegrationHelpers module with methods extracted from Tochtli::Test::Integration
|
29
|
+
* setup and teardown -> before_setup and after_teardown (no need for def setup; super; ... in tests)
|
30
|
+
|
31
|
+
## 0.3.0 / 2015-05-21
|
32
|
+
|
33
|
+
### 4 major enhancements:
|
34
|
+
|
35
|
+
* Process each message in a separate controller instance (`BaseController::Dispatcher` introduced)
|
36
|
+
* Use separate channels and work pools per controller
|
37
|
+
* ControllerManager#start selectively starts controllers
|
38
|
+
* BaseController#start accepts queue name. Multiple queues are supported per single controller.
|
39
|
+
|
40
|
+
### 8 minor enhancements:
|
41
|
+
|
42
|
+
* `queue` & `queue_exists?` methods for TestRabbitConnection
|
43
|
+
* Single reply queue per rabbit connection
|
44
|
+
* configuration_store removed from `RabbitClient` (should be used separately)
|
45
|
+
* `RabbitConnection.logger` default set to `Tochtli.logger`
|
46
|
+
* ActiveRecordConnectionCleaner - a middleware for active connection cleanup
|
47
|
+
* Tochtli.application with middlewares introduced
|
48
|
+
* Network failure recovery rewritten (using automatic bunny recovery with additional reply queue binding recovery)
|
49
|
+
* Bunny logger redirected to RabbitConnection logger with level dependent on Tochtli.debug_bunny (by default WARN)
|
50
|
+
|
51
|
+
### 1 bug fix:
|
52
|
+
|
53
|
+
* `RabbitConnection` logger setup with configuration
|
54
|
+
|
55
|
+
## 0.2.0 / 2015-05-08
|
56
|
+
|
57
|
+
### 1 major enhancement:
|
58
|
+
|
59
|
+
* `RabbitConnection` connection cache. `RabbitConnection.open(configuration_name)` as a standard connection access method.
|
60
|
+
|
61
|
+
### 11 minor enhancements:
|
62
|
+
|
63
|
+
* BaseController callbacks around :start and :setup
|
64
|
+
* Public BaseController#setup method (for manual routing control in tests)
|
65
|
+
* Tochtli::BaseClient tests, expect_published helper method
|
66
|
+
* Tochtli::Message required_attributes and optional_attributes declarations
|
67
|
+
* Tochtli::ServiceCache caches the store object with method: Tochtli::ServiceCache.store
|
68
|
+
* Tochtli::BaseClient singleton methods accept any number of arguments (passed to constructor)
|
69
|
+
* Get rid of ClientProxy. Error handling unified in BaseClient.
|
70
|
+
* Default logger for BaseClient (Tochtli.logger)
|
71
|
+
* Tochtli::Message validation callbacks
|
72
|
+
* Tochtli::Message#ignore_excess_attributes for open messages
|
73
|
+
* assert_published accepts block and yields message
|
74
|
+
|
75
|
+
## 0.1.7 / 2015-04-01
|
76
|
+
|
77
|
+
### 1 minor enhancement:
|
78
|
+
|
79
|
+
* Tochtli::BaseClient introduced (with MessageHandler and SyncMessageHandler)
|
80
|
+
|
81
|
+
## 0.1.6 / 2015-03-02
|
82
|
+
|
83
|
+
### 1 bug fix:
|
84
|
+
|
85
|
+
* Protect RabbitConnection from crash when Rails.root is not set
|
86
|
+
|
87
|
+
## 0.1.5 / 2015-02-06
|
88
|
+
|
89
|
+
### 2 minor enhancement:
|
90
|
+
|
91
|
+
* Test fix: timeout raised
|
92
|
+
* Rails 4.2 compatibility fix
|
93
|
+
|
94
|
+
## 0.1.4 / 2014-11-17
|
95
|
+
|
96
|
+
### 1 minor enhancement:
|
97
|
+
|
98
|
+
* Switched to minitest
|
99
|
+
|
100
|
+
### 1 bug fix:
|
101
|
+
|
102
|
+
* Blocking client proxy should not block on immediate reply (refs #13829)
|
103
|
+
|
104
|
+
## 0.1.3 / 2014-10-28
|
105
|
+
|
106
|
+
### 1 minor enhancement:
|
107
|
+
|
108
|
+
* Remove Rails dependencies
|
109
|
+
|
110
|
+
## 0.1.2 / 2014-10-10
|
111
|
+
|
112
|
+
### 4 minor enhancements:
|
113
|
+
|
114
|
+
* Update corrupted gemspec
|
115
|
+
* Move add_engine_migrations method to hoe-puzzleflow
|
116
|
+
* User always PuzzleFlow gem server
|
117
|
+
* User always PuzzleFlow gem server
|
118
|
+
* rakefile cleaning
|
119
|
+
|
120
|
+
## 0.1.1 / 2014-09-30
|
121
|
+
|
122
|
+
### 1 major enhancement:
|
123
|
+
|
124
|
+
* hoe introduced with git and geminabox integration
|
125
|
+
|
126
|
+
### 1 minor enhancements:
|
127
|
+
|
128
|
+
* do not show ruby warnings (reset RUBY_FLAGS)
|
129
|
+
* hoe-puzzleflow used to unify hoe spec with other PuzzleFlow gems
|
130
|
+
|
131
|
+
## 0.1.0 / 2014-09-29
|
132
|
+
|
133
|
+
### 1 major enhancement
|
134
|
+
|
135
|
+
* Birthday!
|
136
|
+
|
137
|
+
|
138
|
+
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
[](https://travis-ci.org/PuzzleFlow/tochtli)
|
2
|
+
|
3
|
+
# What's Tochtli?
|
4
|
+
|
5
|
+
Tochtli is a set of conventions and tools that simplifies the implementation of components communicating over the RabbitMQ broker.
|
6
|
+
Internally it depends on [bunny](https://github.com/ruby-amqp/bunny) gem.
|
7
|
+
|
8
|
+
## Idea
|
9
|
+
|
10
|
+

|
11
|
+
|
12
|
+
The communication between application and service looks like on the above picture.
|
13
|
+
The _application_ calls the _client_ (regular object) methods which expose the _service API_.
|
14
|
+
The _request_ (a message) is created and sent by the _client_ to the _service queue_ (dedicated queue per service controller).
|
15
|
+
_RabbitMQ_ is used as a message broker and delivers the _request_ to the _service controller_.
|
16
|
+
The _controller_ implements the actions that are performed on the _request_ and may result in the _response_.
|
17
|
+
The _response_ message is published on the _reply queue_ (private for a client connection).
|
18
|
+
The _client_ receives the _response_ and returns the expected result to the _application_.
|
19
|
+
The client methods can be implemented in the blocking and non-blocking (asynchronous) way.
|
20
|
+
|
21
|
+
## Layers
|
22
|
+
|
23
|
+

|
24
|
+
|
25
|
+
The stable service interface really helps to reduce costs of a inevitable change that should only affect the internal implementation.
|
26
|
+
In the proposed above layered structure the application interacts only with the public client class methods.
|
27
|
+
It's not very hard to implement client methods in a such way that they will allow for future changes which won't cause compatibility issues.
|
28
|
+
The expected resistance on the service API changes is a reason way application has no access to the messages definition.
|
29
|
+
Only clients and service controllers operate on the message layer (the common layer).
|
30
|
+
The bottom layer contains tools that allow for communication between the client and the server.
|
31
|
+
There is an option for the message broker agnosticism in the future, because client and service implementation should not directly depend on the particular tool (ex. bunny).
|
32
|
+
|
33
|
+
# What's next?
|
34
|
+
|
35
|
+
Read more about Tochtli and go through the tutorial on [Tochtli homepage](http://puzzleflow.github.io/tochtli).
|
36
|
+
|
37
|
+
# Contributing
|
38
|
+
|
39
|
+
- Fork the project.
|
40
|
+
- Make your feature addition or bug fix.
|
41
|
+
- Add tests for it. This is important so I don't break it in a future version unintentionally.
|
42
|
+
- Send me a pull request.
|
43
|
+
|
44
|
+
# License
|
45
|
+
|
46
|
+
Released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#!/usr/bin/env rake
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
begin
|
7
|
+
Bundler.setup(:default, :development)
|
8
|
+
rescue Bundler::BundlerError => e
|
9
|
+
$stderr.puts e.message
|
10
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
11
|
+
exit e.status_code
|
12
|
+
end
|
13
|
+
require 'rake'
|
14
|
+
|
15
|
+
require 'rake/testtask'
|
16
|
+
require 'jeweler'
|
17
|
+
require 'yard'
|
18
|
+
|
19
|
+
Jeweler::Tasks.new do |gem|
|
20
|
+
# gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
|
21
|
+
gem.name = "tochtli"
|
22
|
+
gem.homepage = "http://github.com/puzzleflow/tochtli"
|
23
|
+
gem.license = "MIT"
|
24
|
+
gem.summary = %Q{Tochtli a core components for SOA}
|
25
|
+
gem.description = %Q{Lightweight framework for service oriented applications based on bunny (RabbitMQ)}
|
26
|
+
gem.email = "rafal.bigaj@puzzleflow.com"
|
27
|
+
gem.authors = ["Rafal Bigaj"]
|
28
|
+
# dependencies defined in Gemfile
|
29
|
+
end
|
30
|
+
Jeweler::RubygemsDotOrgTasks.new
|
31
|
+
|
32
|
+
Rake::TestTask.new(:test) do |test|
|
33
|
+
test.libs << 'lib' << 'test'
|
34
|
+
test.pattern = 'test/**/*_test.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Code coverage detail"
|
39
|
+
task :simplecov do
|
40
|
+
ENV['COVERAGE'] = "true"
|
41
|
+
Rake::Task['test'].execute
|
42
|
+
end
|
43
|
+
|
44
|
+
task :default => :test
|
45
|
+
|
46
|
+
YARD::Rake::YardocTask.new do |t|
|
47
|
+
t.files = ['lib/**/*.rb', 'README*'] # optional
|
48
|
+
t.options = ['--any', '--extra', '--opts'] # optional
|
49
|
+
t.stats_options = ['--list-undoc'] # optional
|
50
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.0
|
Binary file
|
data/assets/layers.png
ADDED
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
Tochtli.logger.progname = 'CLIENT'
|
4
|
+
|
5
|
+
class ScreenerClient < Tochtli::BaseClient
|
6
|
+
def create_screen(url, file_name)
|
7
|
+
handler = SyncMessageHandler.new
|
8
|
+
message = CreateScreenMessage.new(url: url, file: file_name)
|
9
|
+
rabbit_client.publish message, handler: handler
|
10
|
+
handler.wait!(20)
|
11
|
+
puts "Done in #{handler.reply.time} seconds"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
ScreenerClient.new.create_screen(ARGV[0], ARGV[1])
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.require
|
3
|
+
|
4
|
+
Tochtli.logger = Logger.new('tochtli.log')
|
5
|
+
|
6
|
+
class CreateScreenMessage < Tochtli::Message
|
7
|
+
route_to 'screener.create'
|
8
|
+
|
9
|
+
attribute :url, String
|
10
|
+
attribute :file, String
|
11
|
+
end
|
12
|
+
|
13
|
+
class CreateScreenReplyMessage < Tochtli::Message
|
14
|
+
attribute :time, Float
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
Tochtli.logger.progname = 'SERVER'
|
4
|
+
|
5
|
+
class ScreenerController < Tochtli::BaseController
|
6
|
+
bind 'screener.*'
|
7
|
+
|
8
|
+
on CreateScreenMessage, :create
|
9
|
+
|
10
|
+
def create
|
11
|
+
start_time = Time.now
|
12
|
+
f = Screencap::Fetcher.new(message.url)
|
13
|
+
f.fetch output: File.join(__dir__, 'images', message.file)
|
14
|
+
total_time = Time.now - start_time
|
15
|
+
reply CreateScreenReplyMessage.new(time: total_time)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Tochtli::ControllerManager.setup
|
20
|
+
Tochtli::ControllerManager.start
|
21
|
+
|
22
|
+
trap('SIGINT') { exit }
|
23
|
+
at_exit { Tochtli::ControllerManager.stop }
|
24
|
+
|
25
|
+
puts 'Press Ctrl-C to stop worker...'
|
26
|
+
sleep
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
Tochtli.logger.progname = 'CLIENT'
|
4
|
+
|
5
|
+
module LogAnalyzer
|
6
|
+
class Client < Tochtli::BaseClient
|
7
|
+
def send_new_log(path)
|
8
|
+
publish NewLog.new(path: path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def react_on_events(client_id, severities, handler=nil, &block)
|
12
|
+
handler = block unless handler
|
13
|
+
severities = Array(severities)
|
14
|
+
routing_keys = severities.map {|severity| "log.events.#{severity}" }
|
15
|
+
Tochtli::ControllerManager.start EventsController,
|
16
|
+
queue_name: "log_analyzer/events/#{client_id}", # custom queue name
|
17
|
+
routing_keys: routing_keys, # make custom binding (only selected severities)
|
18
|
+
env: { handler: handler }
|
19
|
+
end
|
20
|
+
|
21
|
+
def monitor_status(monitor=nil, &block)
|
22
|
+
monitor = block unless monitor
|
23
|
+
Tochtli::ControllerManager.start MonitorController, env: { monitor: monitor }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
class EventsController < Tochtli::BaseController
|
30
|
+
on EventOccurred, :handle, routing_key: 'log.events.*'
|
31
|
+
|
32
|
+
def handle
|
33
|
+
handler.call(message.severity, message.timestamp, message.message)
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def handler
|
39
|
+
raise "Internal Error: handler not set for EventsController" unless env.has_key?(:handler)
|
40
|
+
env[:handler]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class MonitorController < Tochtli::BaseController
|
45
|
+
bind 'log.status'
|
46
|
+
|
47
|
+
self.queue_name = '' # auto generate
|
48
|
+
self.queue_durable = false
|
49
|
+
self.queue_exclusive = true
|
50
|
+
self.queue_auto_delete = true
|
51
|
+
|
52
|
+
on CurrentStatus do
|
53
|
+
monitor.call(message.to_hash)
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def monitor
|
59
|
+
raise "Internal Error: monitor not set for MonitorController" unless env.has_key?(:monitor)
|
60
|
+
env[:monitor]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
client = LogAnalyzer::Client.new
|
66
|
+
command = ARGV[0]
|
67
|
+
|
68
|
+
def hold
|
69
|
+
puts 'Press Ctrl-C to stop...'
|
70
|
+
sleep
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
case command
|
75
|
+
when 's'
|
76
|
+
client.send_new_log ARGV[1]
|
77
|
+
when 'm'
|
78
|
+
client.monitor_status {|status| p status }
|
79
|
+
hold
|
80
|
+
when 'c'
|
81
|
+
client.react_on_events ARGV[1], [:fatal, :error], lambda {|severity, timestamp, message|
|
82
|
+
puts "[#{timestamp}] Got #{severity}: #{message}"
|
83
|
+
}
|
84
|
+
hold
|
85
|
+
else
|
86
|
+
puts "Unknown command: #{command.inspect}"
|
87
|
+
puts
|
88
|
+
puts "Usage: bundle exec ruby client [command] [params]"
|
89
|
+
puts
|
90
|
+
puts "Commands:"
|
91
|
+
puts " s [path] - send log from file to server"
|
92
|
+
puts " m - start status monitor"
|
93
|
+
puts " c [client ID] - catch fatal and error events"
|
94
|
+
end
|
95
|
+
|