prometheus-splash 0.3.0 → 0.4.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 +4 -4
- data/.github/workflows/ruby.yml +25 -0
- data/CHANGELOG +26 -0
- data/README.md +37 -1
- data/assets/images/splash_design.png +0 -0
- data/bin/splash +9 -1
- data/config/splash.yml +13 -3
- data/lib/splash/backends/file.rb +16 -0
- data/lib/splash/cli/commands.rb +117 -41
- data/lib/splash/cli/config.rb +7 -5
- data/lib/splash/cli/daemon.rb +8 -4
- data/lib/splash/cli/logs.rb +32 -18
- data/lib/splash/commands.rb +17 -16
- data/lib/splash/config.rb +4 -0
- data/lib/splash/config/sanitycheck.rb +23 -19
- data/lib/splash/config/setup.rb +15 -11
- data/lib/splash/constants.rb +9 -5
- data/lib/splash/controller.rb +20 -10
- data/lib/splash/dependencies.rb +3 -0
- data/lib/splash/exiter.rb +4 -2
- data/lib/splash/helpers.rb +30 -4
- data/lib/splash/loggers.rb +89 -0
- data/lib/splash/loggers/cli.rb +83 -0
- data/lib/splash/loggers/daemon.rb +32 -0
- data/lib/splash/loggers/dual.rb +22 -0
- data/lib/splash/logs.rb +4 -3
- data/lib/splash/orchestrator.rb +17 -8
- data/lib/splash/orchestrator/grammar.rb +13 -6
- data/lib/splash/transports.rb +2 -2
- data/lib/splash/transports/rabbitmq.rb +16 -2
- data/prometheus-splash.gemspec +2 -1
- metadata +23 -2
data/lib/splash/controller.rb
CHANGED
@@ -6,25 +6,34 @@ module Splash
|
|
6
6
|
include Splash::Helpers
|
7
7
|
include Splash::Config
|
8
8
|
include Splash::Orchestrator
|
9
|
+
include Splash::Exiter
|
10
|
+
include Splash::Loggers
|
9
11
|
|
10
12
|
def startdaemon(options = {})
|
11
13
|
config = get_config
|
14
|
+
log = get_logger
|
12
15
|
unless verify_service host: config.prometheus_pushgateway_host ,port: config.prometheus_pushgateway_port then
|
13
16
|
return {:case => :service_dependence_missing, :more => 'Prometheus Gateway'}
|
14
17
|
end
|
15
18
|
unless File::exist? config.full_pid_path then
|
16
|
-
|
19
|
+
daemon_config = {:description => config.daemon_process_name,
|
17
20
|
:pid_file => config.full_pid_path,
|
18
21
|
:stdout_trace => config.full_stdout_trace_path,
|
19
|
-
:stderr_trace => config.full_stderr_trace_path,
|
22
|
+
:stderr_trace => config.full_stderr_trace_path,
|
23
|
+
:foreground => options[:foreground]
|
24
|
+
}
|
25
|
+
|
26
|
+
["int","term","hup"].each do |type| daemon_config["sig#{type}_handler".to_sym] = Proc::new { ObjectSpace.each_object(Splash::Orchestrator::Scheduler).first.shutdown } end
|
27
|
+
res = daemonize daemon_config do
|
20
28
|
Scheduler::new options
|
21
29
|
end
|
30
|
+
sleep 1
|
22
31
|
if res == 0 then
|
23
32
|
pid = `cat #{config.full_pid_path}`.to_i
|
24
|
-
|
25
|
-
return {:case => :quiet_exit}
|
33
|
+
log.ok "Splash Daemon Started, with PID : #{pid}"
|
34
|
+
return {:case => :quiet_exit, :more => "Splash Daemon successfully loaded."}
|
26
35
|
else
|
27
|
-
return {:case => :unknown_error, :more => "Splash Daemon loading error, see logs for more details"}
|
36
|
+
return {:case => :unknown_error, :more => "Splash Daemon loading error, see logs for more details."}
|
28
37
|
end
|
29
38
|
|
30
39
|
else
|
@@ -49,7 +58,8 @@ module Splash
|
|
49
58
|
return acase
|
50
59
|
end
|
51
60
|
|
52
|
-
def statusdaemon
|
61
|
+
def statusdaemon(options = {})
|
62
|
+
log = get_logger
|
53
63
|
config = get_config
|
54
64
|
pid = realpid = ''
|
55
65
|
pid = `cat #{config.full_pid_path}`.to_s if File.exist?(config.full_pid_path)
|
@@ -57,14 +67,14 @@ module Splash
|
|
57
67
|
pid.chomp!
|
58
68
|
realpid.chomp!
|
59
69
|
unless realpid.empty? then
|
60
|
-
|
70
|
+
log.item "Splash Process is running with PID #{realpid} "
|
61
71
|
else
|
62
|
-
|
72
|
+
log.item 'Splash Process not found '
|
63
73
|
end
|
64
74
|
unless pid.empty? then
|
65
|
-
|
75
|
+
log.item "and PID file exist with PID #{pid}"
|
66
76
|
else
|
67
|
-
|
77
|
+
log.item "and PID file don't exist"
|
68
78
|
end
|
69
79
|
if pid == realpid then
|
70
80
|
return {:case => :status_ok }
|
data/lib/splash/dependencies.rb
CHANGED
@@ -24,6 +24,7 @@ module Splash
|
|
24
24
|
require 'rufus-scheduler'
|
25
25
|
require 'tty-markdown'
|
26
26
|
require 'tty-pager'
|
27
|
+
require 'colorize'
|
27
28
|
require "redis"
|
28
29
|
|
29
30
|
rescue Gem::GemNotFoundException
|
@@ -37,11 +38,13 @@ module Splash
|
|
37
38
|
require 'splash/constants'
|
38
39
|
require 'splash/helpers'
|
39
40
|
require 'splash/config'
|
41
|
+
require 'splash/loggers'
|
40
42
|
require 'splash/exiter'
|
41
43
|
require 'splash/templates'
|
42
44
|
require 'splash/backends'
|
43
45
|
require 'splash/transports'
|
44
46
|
|
47
|
+
|
45
48
|
require 'splash/commands'
|
46
49
|
require 'splash/logs'
|
47
50
|
require 'splash/orchestrator'
|
data/lib/splash/exiter.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
module Splash
|
3
3
|
module Exiter
|
4
|
+
include Splash::Loggers
|
4
5
|
EXIT_MAP= {
|
5
6
|
|
6
7
|
# context execution
|
@@ -34,15 +35,16 @@ module Splash
|
|
34
35
|
}
|
35
36
|
|
36
37
|
def splash_exit(options = {})
|
38
|
+
log = get_logger
|
37
39
|
mess = ""
|
38
40
|
mess = EXIT_MAP[options[:case]][:message] if EXIT_MAP[options[:case]].include? :message
|
39
41
|
mess << " : " unless mess.empty? or not options[:more]
|
40
42
|
mess << "#{options[:more]}" if options[:more]
|
41
43
|
if EXIT_MAP[options[:case]][:code] == 0 then
|
42
|
-
|
44
|
+
log.success mess unless mess.empty?
|
43
45
|
exit 0
|
44
46
|
else
|
45
|
-
|
47
|
+
log.fatal mess unless mess.empty?
|
46
48
|
exit EXIT_MAP[options[:case]][:code]
|
47
49
|
end
|
48
50
|
end
|
data/lib/splash/helpers.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# @option options [String] :stdout_trace the path of the file where to redirect STDOUT
|
1
2
|
# coding: utf-8
|
2
3
|
module Splash
|
3
4
|
module Helpers
|
@@ -89,6 +90,9 @@ module Splash
|
|
89
90
|
# @option options [String] :daemon_group the group to change privileges
|
90
91
|
# @option options [String] :stderr_trace the path of the file where to redirect STDERR
|
91
92
|
# @option options [String] :stdout_trace the path of the file where to redirect STDOUT
|
93
|
+
# @option options [Proc] :sigint_handler handler Proc for SIGINT signal
|
94
|
+
# @option options [Proc] :sigterm_handler handler Proc for SIGTERM signal
|
95
|
+
# @option options [Proc] :sighup_handler handler Proc for SIGHuP signal
|
92
96
|
# @option options [Bool] :foreground option to run foreground
|
93
97
|
# @yield a process definion or block given
|
94
98
|
# @example usage inline
|
@@ -129,11 +133,33 @@ module Splash
|
|
129
133
|
#Process.euid = 0
|
130
134
|
#Process.egid = 0
|
131
135
|
|
132
|
-
trap("SIGINT"){
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
+
trap("SIGINT"){
|
137
|
+
if options[:sigint_handler] then
|
138
|
+
options[:sigint_handler].call
|
139
|
+
else
|
140
|
+
exit! 0
|
141
|
+
end
|
142
|
+
}
|
143
|
+
trap("SIGTERM"){
|
144
|
+
if options[:sigterm_handler] then
|
145
|
+
options[:sigterm_handler].call
|
146
|
+
else
|
147
|
+
exit! 0
|
148
|
+
end
|
149
|
+
}
|
150
|
+
trap("SIGHUP"){
|
151
|
+
if options[:sighup_handler] then
|
152
|
+
options[:sighup_handler].call
|
153
|
+
else
|
154
|
+
exit! 0
|
155
|
+
end
|
156
|
+
}
|
157
|
+
if options[:foreground]
|
158
|
+
change_logger logger: :dual
|
159
|
+
return yield
|
160
|
+
end
|
136
161
|
fork do
|
162
|
+
change_logger logger: :daemon
|
137
163
|
#Process.daemon
|
138
164
|
File.open(options[:pid_file],"w"){|f| f.puts Process.pid } if options[:pid_file]
|
139
165
|
if options[:daemon_user] and options[:daemon_group] then
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
module Splash
|
5
|
+
module Loggers
|
6
|
+
include Splash::Config
|
7
|
+
|
8
|
+
@@logger=nil
|
9
|
+
|
10
|
+
def get_logger(options = {})
|
11
|
+
logger = (get_config.loggers[:list].include? options[:logger])? options[:logger].to_s : get_config.loggers[:default].to_s
|
12
|
+
aclass = "Splash::Loggers::#{logger.capitalize}"
|
13
|
+
# begin
|
14
|
+
return @@logger = Kernel.const_get(aclass)::new if options[:force]
|
15
|
+
return @@logger ||= Kernel.const_get(aclass)::new
|
16
|
+
# rescue
|
17
|
+
# splash_exit case: :configuration_error, more: "Logger specified inexistant : #{logger}"
|
18
|
+
# end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def change_logger(options = {})
|
23
|
+
options[:force] = true
|
24
|
+
get_logger(options)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
class LoggerTemplate
|
30
|
+
include Splash::Config
|
31
|
+
|
32
|
+
LEVELS = [:debug, :warn, :info, :result, :fatal, :unknown]
|
33
|
+
ALIAS = {:flat => :info, :item => :info, :ok => :info, :ko => :info, :trigger => :info,
|
34
|
+
:schedule => :info, :arrow => :info, :send => :info,
|
35
|
+
:receive => :info, :error => :result, :success => :result }
|
36
|
+
LEVELS.each do |method|
|
37
|
+
define_method(method) do |message|
|
38
|
+
self.log({ :level => method, :message => message})
|
39
|
+
end
|
40
|
+
end
|
41
|
+
ALIAS.keys.each do |method|
|
42
|
+
define_method(method) do |message|
|
43
|
+
self.log({ :level => method, :message => message})
|
44
|
+
end
|
45
|
+
end
|
46
|
+
def initialize
|
47
|
+
self.level = get_config.loggers[:level]
|
48
|
+
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def log(options)
|
54
|
+
level = (ALIAS.keys.include? options[:level])? ALIAS[options[:level]] : options[:level]
|
55
|
+
if @active_levels.include? level then
|
56
|
+
puts options[:message]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def level
|
62
|
+
return @active_levels.first
|
63
|
+
end
|
64
|
+
|
65
|
+
def level=(level)
|
66
|
+
if LEVELS.include? level then
|
67
|
+
@active_levels = LEVELS.dup
|
68
|
+
@active_levels.shift(LEVELS.index(level))
|
69
|
+
else
|
70
|
+
raise BadLevel
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
private
|
76
|
+
def alt(symbol)
|
77
|
+
return "=>" if symbol == :arrow
|
78
|
+
return '' if symbol == :flat
|
79
|
+
return symbol.to_s.upcase
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
class BadLevel < Exception; end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
Dir[File.dirname(__FILE__) + '/loggers/*.rb'].each {|file| require file }
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Splash
|
3
|
+
module Loggers
|
4
|
+
|
5
|
+
class Cli < Splash::Loggers::LoggerTemplate
|
6
|
+
|
7
|
+
include Splash::Config
|
8
|
+
|
9
|
+
EMOJI = { :unknown => "\u{1F4A5}",
|
10
|
+
:fatal => "\u{26D4}",
|
11
|
+
:error => "\u{1F6AB}",
|
12
|
+
:ko => "\u{1F44E}",
|
13
|
+
:warn => "\u{26A0}",
|
14
|
+
:info => "\u{2139}",
|
15
|
+
:item => " \u{1F539}",
|
16
|
+
:arrow => " \u{27A1}",
|
17
|
+
:schedule => "\u{23F1}",
|
18
|
+
:trigger => "\u{23F0}",
|
19
|
+
:send => "\u{1F4E4}",
|
20
|
+
:receive => "\u{1F4E5}",
|
21
|
+
:ok => "\u{1F44D}",
|
22
|
+
:success => "\u{1F4AA}",
|
23
|
+
:debug => "\u{1F41B}"}
|
24
|
+
|
25
|
+
COLORS = { :unknown => :red,
|
26
|
+
:fatal => :red,
|
27
|
+
:error => :red,
|
28
|
+
:ko => :yellow,
|
29
|
+
:warn => :yellow,
|
30
|
+
:item => :white,
|
31
|
+
:arrow => :white,
|
32
|
+
:send => :white,
|
33
|
+
:schedule => :white,
|
34
|
+
:trigger => :white,
|
35
|
+
:receive => :white,
|
36
|
+
:info => :cyan,
|
37
|
+
:ok => :green,
|
38
|
+
:success => :green,
|
39
|
+
:debug => :magenta}
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
def log(options)
|
44
|
+
level = (ALIAS.keys.include? options[:level])? ALIAS[options[:level]] : options[:level]
|
45
|
+
if @active_levels.include? level then
|
46
|
+
if options[:level] == :flat then
|
47
|
+
puts options[:message]
|
48
|
+
else
|
49
|
+
String.disable_colorization = !get_config.loggers[:cli][:color]
|
50
|
+
emoji = get_config.loggers[:cli][:emoji]
|
51
|
+
emoji = check_unicode_term if emoji
|
52
|
+
if emoji then
|
53
|
+
display = "#{EMOJI[options[:level]]} #{options[:message]}"
|
54
|
+
else
|
55
|
+
display = "#{alt(options[:level])} #{options[:message]}"
|
56
|
+
end
|
57
|
+
puts display.colorize(COLORS[options[:level]])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def emoji=(status)
|
63
|
+
get_config.loggers[:cli][:emoji] = status
|
64
|
+
end
|
65
|
+
|
66
|
+
def color=(status)
|
67
|
+
get_config.loggers[:cli][:color] = status
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_unicode_term
|
71
|
+
if ENV.values_at("LC_ALL","LC_CTYPE","LANG").compact.first.include?("UTF-8") and ENV.values_at('TERM').first.include? "xterm" then
|
72
|
+
return true
|
73
|
+
else
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
class BadLevel < Exception; end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Splash
|
3
|
+
module Loggers
|
4
|
+
|
5
|
+
|
6
|
+
class Daemon < Splash::Loggers::LoggerTemplate
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
self.level = get_config.loggers[:level]
|
12
|
+
@log_file = get_config.loggers[:daemon][:file]
|
13
|
+
@stream = File::open(@log_file, 'a')
|
14
|
+
@stream.sync = true
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def log(options)
|
19
|
+
level = (ALIAS.keys.include? options[:level])? ALIAS[options[:level]] : options[:level]
|
20
|
+
if @active_levels.include? level then
|
21
|
+
@stream.puts "#{alt(options[:level])} #{options[:message]}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def close
|
26
|
+
@stream.close
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Splash
|
2
|
+
module Loggers
|
3
|
+
|
4
|
+
class Dual < Splash::Loggers::LoggerTemplate
|
5
|
+
include Splash::Config
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
super
|
11
|
+
@log1 = Splash::Loggers::Cli::new
|
12
|
+
@log2 = Splash::Loggers::Daemon::new
|
13
|
+
end
|
14
|
+
|
15
|
+
def log(options)
|
16
|
+
@log1.log options
|
17
|
+
@log2.log options
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/splash/logs.rb
CHANGED
@@ -43,13 +43,14 @@ module Splash
|
|
43
43
|
|
44
44
|
# start notification on prometheus for metric logerrors, logmissing; loglines
|
45
45
|
def notify
|
46
|
+
log = get_logger
|
46
47
|
unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
|
47
48
|
return { :case => :service_dependence_missing, :more => "Prometheus Notification not send." }
|
48
49
|
end
|
49
|
-
|
50
|
+
log.info "Sending metrics to Prometheus Pushgateway"
|
50
51
|
@logs_target.each do |item|
|
51
52
|
missing = (item[:status] == :missing)? 1 : 0
|
52
|
-
|
53
|
+
log.item "Sending metrics for #{item[:log]}"
|
53
54
|
@metric_count.set(item[:count], labels: { log: item[:log] })
|
54
55
|
@metric_missing.set(missing, labels: { log: item[:log] })
|
55
56
|
lines = (item[:lines])? item[:lines] : 0
|
@@ -58,7 +59,7 @@ module Splash
|
|
58
59
|
hostname = Socket.gethostname
|
59
60
|
url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
|
60
61
|
Prometheus::Client::Push.new('Splash',hostname, url).add(@registry)
|
61
|
-
|
62
|
+
log.ok "Sending to Prometheus PushGateway done."
|
62
63
|
return {:case => :quiet_exit }
|
63
64
|
end
|
64
65
|
|
data/lib/splash/orchestrator.rb
CHANGED
@@ -12,27 +12,30 @@ module Splash
|
|
12
12
|
include Splash::Config
|
13
13
|
include Splash::Transports
|
14
14
|
include Splash::Orchestrator::Grammar
|
15
|
+
include Splash::Loggers
|
16
|
+
|
15
17
|
def initialize(options = {})
|
18
|
+
@log = get_logger
|
16
19
|
$stdout.sync = true
|
17
20
|
$stderr.sync = true
|
18
21
|
@server = Rufus::Scheduler::new
|
19
22
|
@server.extend SchedulerHooks
|
20
23
|
@config = get_config
|
21
24
|
@result = LogScanner::new
|
22
|
-
|
25
|
+
@log.info "Splash Orchestrator starting :"
|
23
26
|
if options[:scheduling] then
|
24
|
-
|
27
|
+
@log.item "Initializing commands Scheduling."
|
25
28
|
self.init_commands_scheduling
|
26
29
|
end
|
27
30
|
sched,value = @config.daemon_logmon_scheduling.flatten
|
28
|
-
|
31
|
+
@log.item "Initializing logs monitorings & notifications."
|
29
32
|
@server.send sched,value do
|
30
33
|
begin
|
34
|
+
@log.trigger "Logs monitoring for Scheduling : #{sched.to_s} #{value.to_s}"
|
31
35
|
@result.analyse
|
32
36
|
@result.notify
|
33
|
-
$stdout.flush
|
34
37
|
rescue Errno::ECONNREFUSED
|
35
|
-
|
38
|
+
@log.error "PushGateway seems to be done, please start it."
|
36
39
|
end
|
37
40
|
end
|
38
41
|
hostname = Socket.gethostname
|
@@ -43,21 +46,26 @@ module Splash
|
|
43
46
|
transport.subscribe(:block => true) do |delivery_info, properties, body|
|
44
47
|
content = YAML::load(body)
|
45
48
|
if VERBS.include? content[:verb]
|
46
|
-
|
49
|
+
@log.receive "Valid remote order, verb : #{content[:verb].to_s}"
|
47
50
|
if content[:payload] then
|
48
51
|
res = self.send content[:verb], content[:payload]
|
49
52
|
else
|
50
53
|
res = self.send content[:verb]
|
51
54
|
end
|
52
55
|
get_default_client.publish queue: content[:return_to], message: res.to_yaml
|
56
|
+
@log.send "Result to #{content[:return_to]}."
|
53
57
|
else
|
54
|
-
|
58
|
+
@log.receive "INVALID remote order, verb : #{content[:verb].to_s}"
|
55
59
|
get_default_client.publish queue: content[:return_to], message: "Unkown verb #{content[:verb]}".to_yaml
|
56
60
|
end
|
57
61
|
end
|
58
62
|
end
|
59
63
|
|
60
64
|
def terminate
|
65
|
+
@log.info "Splash daemon shutdown"
|
66
|
+
@server.shutdown
|
67
|
+
change_logger logger: :cli
|
68
|
+
splash_exit case: :quiet_exit
|
61
69
|
end
|
62
70
|
|
63
71
|
private
|
@@ -66,8 +74,9 @@ module Splash
|
|
66
74
|
commands = config.select{|key,value| value.include? :schedule}.keys
|
67
75
|
commands.each do |command|
|
68
76
|
sched,value = config[command][:schedule].flatten
|
69
|
-
|
77
|
+
@log.arrow "Scheduling command #{command.to_s}"
|
70
78
|
@server.send sched,value do
|
79
|
+
@log.trigger "Executing Scheduled command #{command.to_s} for Scheduling : #{sched.to_s} #{value.to_s}"
|
71
80
|
self.execute command: command.to_s
|
72
81
|
end
|
73
82
|
end
|