monus 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a04a518fe2178f143970691645c51fc69d67bc1f
4
+ data.tar.gz: b09f0a47c40336df387a103067b0480a894e73c2
5
+ SHA512:
6
+ metadata.gz: c7d50f18c451e64f516fed6fd8fd1ca71b0d752697c637bd22f6d5a7a5cbf020ec7f0784c4a22970d69daff0d167282c3aba73cf745c8b3df055aa1d946e3f8b
7
+ data.tar.gz: 8c80f5383c4d89ef962851b69398c210be0a4c0a707a10781e41aaeabfe6e0c549cdc7cd83bb91ff95dfe4b15025d3725777b8850441f42ab9c62336b8c506f8
data/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2018 Aleksandr Kundin
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Monus
2
+
3
+ Monus is the proof-of-concept monitoring library. Detailed description will be available (hope) in future.
data/lib/monus.rb ADDED
@@ -0,0 +1,69 @@
1
+ module Monus
2
+ ConfigurationError = Class.new StandardError
3
+
4
+ @@prepared = false
5
+ @@preparing = false
6
+ @@options = {}
7
+
8
+ def self.configure(options)
9
+ @@options = options
10
+ prepare
11
+ end
12
+
13
+ def self.options
14
+ @@options
15
+ end
16
+
17
+ def self.prepare
18
+ return true if @@prepared or @@preparing
19
+ @@preparing = true
20
+
21
+ prepare_logger if options[:logger]
22
+
23
+ @@engine = Monus::Engine[options[:engine] || :pure]
24
+ @@engine.prepare
25
+
26
+ @@backend = Monus::Backend[options[:backend] || :memory]
27
+ @@backend.prepare
28
+
29
+ options[:built_in_metrics]&.each do |metric|
30
+ Monus::BuiltInMetric[metric].activate
31
+ end
32
+
33
+ @@preparing = false
34
+ @@prepared = true
35
+ end
36
+
37
+ def self.engine
38
+ prepare unless @@prepared
39
+ @@engine
40
+ end
41
+
42
+ def self.backend
43
+ prepare unless @@prepared
44
+ @@backend
45
+ end
46
+
47
+ def self.logger
48
+ @@logger ||= options[:logger] || begin
49
+ require 'logger'
50
+ Logger.new STDOUT
51
+ end
52
+ end
53
+
54
+ def self.set(field, value)
55
+ backend.write field, value
56
+ end
57
+
58
+ def self.accept(field)
59
+ set field, true
60
+ end
61
+
62
+ def self.refuse(field)
63
+ set field, false
64
+ end
65
+ end
66
+
67
+ require_relative 'monus/engine'
68
+ require_relative 'monus/backend'
69
+ require_relative 'monus/built_in_metric'
@@ -0,0 +1,15 @@
1
+ module Monus::Backend
2
+ @@backends = {}
3
+
4
+ def self.register(name, object)
5
+ @@backends[name] = object
6
+ end
7
+
8
+ def self.[](name)
9
+ @@backends[name] or raise NotImplementedError, "no such backend: #{name.inspect}, possible backends are: #{@@backends.keys.map(&:inspect) * ', '}"
10
+ end
11
+ end
12
+
13
+ backends_glob = File.join File.dirname(__FILE__), 'backends', '*.rb'
14
+ backends_files = Dir[backends_glob].map &File.method(:absolute_path)
15
+ backends_files.each &method(:require)
@@ -0,0 +1,52 @@
1
+ module Monus::Backend::InfluxDB
2
+ def prepare
3
+ @host = Monus.options.dig(:influxdb_options, :host) || 'localhost'
4
+
5
+ @measurement = Monus.options.dig(:influxdb_options, :measurement)
6
+ unless @measurement
7
+ raise Monus::ConfigurationError, 'when using InfluxDB backend you should provide `influxdb_options/measurement` configuration with measurement (table) name'
8
+ end
9
+
10
+ @mode = Monus.options.dig(:influxdb_options, :mode)
11
+ case @mode
12
+ when :udp
13
+ @udp_port = Monus.options.dig(:influxdb_options, :udp_port)
14
+ unless @udp_port
15
+ raise Monus::ConfigurationError, 'when using UDP mode you should provide `influxdb_options/udp_port` configuration with corresponding port number'
16
+ end
17
+ when :http
18
+ @http_port = Monus.options.dig(:influxdb_options, :http_port)
19
+ unless @http_port
20
+ raise Monus::ConfigurationError, 'when using HTTP mode you should provide `influxdb_options/http_port` configuration with corresponding port number'
21
+ end
22
+
23
+ @database = Monus.options.dig(:influxdb_options, :database)
24
+ unless @database
25
+ raise Monus::ConfigurationError, 'when using HTTP mode you should provide `influxdb_options/database` configuration with database name'
26
+ end
27
+
28
+ @http_connection = Monus.engine.make_http_connection @host, @http_port
29
+
30
+ @uri = "/write?db=#{@database}"
31
+ else
32
+ raise Monus::ConfigurationError, 'when using InfluxDB backend you should provide `influxdb_options/mode` configuration with `:udp` or `:http` value'
33
+ end
34
+
35
+ @global_tags = Monus.options.dig(:influxdb_options, :global_tags)&.map { |key, value| ",#{key}=#{value}" }&.join
36
+ end
37
+
38
+ def write(field, value)
39
+ value = "\"#{value.gsub '"', '\"'}\"" if value.kind_of? String
40
+ message = "#{@measurement}#{@global_tags} #{field}=#{value}"
41
+ case @mode
42
+ when :udp
43
+ Monus.engine.send_udp_datagram message, @host, @udp_port
44
+ when :http
45
+ Monus.engine.send_http_request @uri, method: :post, body: message, connection: @http_connection
46
+ end
47
+ end
48
+
49
+ extend self
50
+
51
+ Monus::Backend.register :influxdb, self
52
+ end
@@ -0,0 +1,15 @@
1
+ module Monus::BuiltInMetric
2
+ @@metrics = {}
3
+
4
+ def self.register(name, object)
5
+ @@metrics[name] = object
6
+ end
7
+
8
+ def self.[](name)
9
+ @@metrics[name] or raise NotImplementedError, "no such metric: #{name.inspect}, possible metrics are: #{@@metrics.keys.map(&:inspect) * ', '}"
10
+ end
11
+ end
12
+
13
+ metrics_glob = File.join File.dirname(__FILE__), 'built_in_metrics', '*.rb'
14
+ metrics_files = Dir[metrics_glob].map &File.method(:absolute_path)
15
+ metrics_files.each &method(:require)
@@ -0,0 +1,13 @@
1
+ module Monus::BuiltInMetric::Works
2
+ def activate
3
+ @interval = Monus.options.dig(:works_metric_options, :interval) || 1
4
+
5
+ Monus.engine.every @interval do
6
+ Monus.accept :works
7
+ end
8
+ end
9
+
10
+ extend self
11
+
12
+ Monus::BuiltInMetric.register :works, self
13
+ end
@@ -0,0 +1,15 @@
1
+ module Monus::Engine
2
+ @@engines = {}
3
+
4
+ def self.register(name, object)
5
+ @@engines[name] = object
6
+ end
7
+
8
+ def self.[](name)
9
+ @@engines[name] or raise NotImplementedError, "no such engine: #{name.inspect}, possible engines are: #{@@engines.keys.map(&:inspect) * ', '}"
10
+ end
11
+ end
12
+
13
+ engines_glob = File.join File.dirname(__FILE__), 'engines', '*.rb'
14
+ engines_files = Dir[engines_glob].map &File.method(:absolute_path)
15
+ engines_files.each &method(:require)
@@ -0,0 +1,90 @@
1
+ module Monus::Engine::Pure
2
+ def initialize_defaults
3
+ @on_error ||= []
4
+ end
5
+
6
+ def prepare
7
+ initialize_defaults
8
+ option = Monus.options.dig(:pure_engine_options, :on_async_error)
9
+ case option
10
+ when Array
11
+ option.each &method(:add_error_handler)
12
+ else
13
+ add_error_handler option
14
+ end
15
+ @prepared = true
16
+ end
17
+
18
+ def add_error_handler(handler)
19
+ initialize_defaults
20
+ @on_error.push case handler
21
+ when Proc
22
+ handler
23
+ when :crash
24
+ -> * { exit 1 }
25
+ when :ignore
26
+ -> * {}
27
+ when :break
28
+ -> error, * { raise error }
29
+ when :log, nil
30
+ -> error, type, * { Monus.logger.fatal "error in Monus #{type} - #{error.class}: #{error.message}\n#{error.backtrace * "\n"}" }
31
+ else
32
+ raise Monus::ConfigurationError, 'unknown error handler given in `pure_engine_options/on_async_error` configuration; it should be a block (exception, type and binding arguments will passed) or one of `:crash`, `:ignore`, `:break` or `:log` (default) values, or array of them'
33
+ end
34
+ end
35
+
36
+ def make_http_connection(host, port)
37
+ load_http
38
+ Net::HTTP.start host, port
39
+ end
40
+
41
+ def send_http_request(uri, method: :get, body: nil, connection: Net::HTTP)
42
+ load_http
43
+ uri = URI.parse uri if connection == Net::HTTP and not uri.kind_of?(URI)
44
+ case method
45
+ when :get then connection.get uri
46
+ when :post then connection.post uri, body
47
+ else raise NotImplementedError, "unknown HTTP method #{method.inspect}"
48
+ end
49
+ end
50
+
51
+ def load_http
52
+ @http_loaded ||= begin
53
+ require 'net/http'
54
+ require 'uri'
55
+ true
56
+ end
57
+ end
58
+
59
+ def send_udp_datagram(message, host, port)
60
+ @udp_socket ||= begin
61
+ require 'socket'
62
+ UDPSocket.new
63
+ end
64
+ @udp_socket.send message, 0, host, port
65
+ end
66
+
67
+ def every(interval, fire_immediately: true, on_error: nil, &block)
68
+ prepare unless @prepared
69
+
70
+ Thread.new do
71
+ sleep interval unless fire_immediately
72
+
73
+ loop do
74
+ begin
75
+ block.call
76
+ rescue => error
77
+ interval_binding = binding
78
+ Array(on_error || @on_error).each do |handler|
79
+ handler.call error, :interval, interval_binding
80
+ end
81
+ end
82
+ sleep interval
83
+ end
84
+ end
85
+ end
86
+
87
+ extend self
88
+
89
+ Monus::Engine.register :pure, self
90
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: monus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Xanders
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-09-23 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Monus is an in-process monitoring library for several backends and engines
14
+ email: necropolis@inbox.ru
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - LICENSE.md
20
+ - README.md
21
+ - lib/monus.rb
22
+ - lib/monus/backend.rb
23
+ - lib/monus/backends/influxdb.rb
24
+ - lib/monus/built_in_metric.rb
25
+ - lib/monus/built_in_metrics/works.rb
26
+ - lib/monus/engine.rb
27
+ - lib/monus/engines/pure.rb
28
+ homepage: https://github.com/xanders/monus.rb
29
+ licenses:
30
+ - MIT
31
+ metadata: {}
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 2.6.13
49
+ signing_key:
50
+ specification_version: 4
51
+ summary: God of Monitoring
52
+ test_files: []