monus 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +7 -0
- data/README.md +3 -0
- data/lib/monus.rb +69 -0
- data/lib/monus/backend.rb +15 -0
- data/lib/monus/backends/influxdb.rb +52 -0
- data/lib/monus/built_in_metric.rb +15 -0
- data/lib/monus/built_in_metrics/works.rb +13 -0
- data/lib/monus/engine.rb +15 -0
- data/lib/monus/engines/pure.rb +90 -0
- metadata +52 -0
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
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
|
data/lib/monus/engine.rb
ADDED
@@ -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: []
|