prometheus-splash 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/cli/config.rb
CHANGED
@@ -2,19 +2,20 @@
|
|
2
2
|
module CLISplash
|
3
3
|
|
4
4
|
class Config < Thor
|
5
|
-
include Splash::
|
5
|
+
include Splash::ConfigUtilities
|
6
6
|
include Splash::Helpers
|
7
7
|
include Splash::Exiter
|
8
|
+
include Splash::Loggers
|
8
9
|
|
9
10
|
|
10
11
|
desc "setup", "Setup installation fo Splash"
|
11
12
|
long_desc <<-LONGDESC
|
12
|
-
Setup installation fo Splash
|
13
|
+
Setup installation fo Splash\n
|
13
14
|
with --preserve, preserve from reinstallation of the config
|
14
15
|
LONGDESC
|
15
16
|
option :preserve, :type => :boolean
|
16
17
|
def setup
|
17
|
-
acase = run_as_root :setupsplash
|
18
|
+
acase = run_as_root :setupsplash, options
|
18
19
|
splash_exit acase
|
19
20
|
end
|
20
21
|
|
@@ -26,9 +27,10 @@ module CLISplash
|
|
26
27
|
|
27
28
|
desc "version", "display current Splash version"
|
28
29
|
def version
|
30
|
+
log = get_logger
|
29
31
|
config = get_config
|
30
|
-
|
31
|
-
|
32
|
+
log.info "Splash version : #{config.version}, Author : #{config.author}"
|
33
|
+
log_info config.copyright
|
32
34
|
splash_exit case: :quiet_exit
|
33
35
|
end
|
34
36
|
|
data/lib/splash/cli/daemon.rb
CHANGED
@@ -5,6 +5,7 @@ module CLISplash
|
|
5
5
|
include Splash::LogsMonitor::DaemonController
|
6
6
|
include Splash::Transports
|
7
7
|
include Splash::Exiter
|
8
|
+
include Splash::Loggers
|
8
9
|
|
9
10
|
|
10
11
|
option :foreground, :type => :boolean
|
@@ -18,6 +19,7 @@ module CLISplash
|
|
18
19
|
LONGDESC
|
19
20
|
desc "start", "Starting Splash Daemon"
|
20
21
|
def start
|
22
|
+
log = get_logger
|
21
23
|
if options[:purge] then
|
22
24
|
transport = get_default_client
|
23
25
|
if transport.class == Hash and transport.include? :case then
|
@@ -25,7 +27,7 @@ module CLISplash
|
|
25
27
|
else
|
26
28
|
queue = "splash.#{Socket.gethostname}.input"
|
27
29
|
transport.purge queue: queue
|
28
|
-
|
30
|
+
log.info "Queue : #{queue} purged"
|
29
31
|
end
|
30
32
|
end
|
31
33
|
acase = run_as_root :startdaemon, options
|
@@ -35,13 +37,14 @@ module CLISplash
|
|
35
37
|
|
36
38
|
desc "purge", "Purge Transport Input queue of Daemon"
|
37
39
|
def purge
|
40
|
+
log = get_logger
|
38
41
|
transport = get_default_client
|
39
42
|
if transport.class == Hash and transport.include? :case then
|
40
43
|
splash_exit transport
|
41
44
|
else
|
42
45
|
queue = "splash.#{Socket.gethostname}.input"
|
43
46
|
transport.purge queue: queue
|
44
|
-
|
47
|
+
log.ok "Queue : #{queue} purged"
|
45
48
|
splash_exit case: :quiet_exit
|
46
49
|
end
|
47
50
|
end
|
@@ -60,13 +63,14 @@ module CLISplash
|
|
60
63
|
|
61
64
|
desc "ping HOSTNAME", "send a ping to HOSTNAME daemon over transport (need an active tranport), Typicallly RabbitMQ"
|
62
65
|
def ping(hostname=Socket.gethostname)
|
63
|
-
|
66
|
+
log = get_logger
|
67
|
+
log.info "ctrl+c for interrupt"
|
64
68
|
begin
|
65
69
|
transport = get_default_client
|
66
70
|
if transport.class == Hash and transport.include? :case then
|
67
71
|
splash_exit transport
|
68
72
|
else
|
69
|
-
|
73
|
+
log.receive transport.execute({ :verb => :ping,
|
70
74
|
:payload => {:hostname => Socket.gethostname},
|
71
75
|
:return_to => "splash.#{Socket.gethostname}.returncli",
|
72
76
|
:queue => "splash.#{hostname}.input" })
|
data/lib/splash/cli/logs.rb
CHANGED
@@ -8,21 +8,33 @@ module CLISplash
|
|
8
8
|
|
9
9
|
desc "analyse", "analyze logs in config"
|
10
10
|
def analyse
|
11
|
+
log = get_logger
|
11
12
|
results = Splash::LogScanner::new
|
12
13
|
res = results.analyse
|
13
|
-
|
14
|
+
log.info "SPlash Configured logs status :"
|
14
15
|
full_status = true
|
15
16
|
results.output.each do |result|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
if result[:status] == :clean then
|
18
|
+
log.ok "Log : #{result[:log]} : no errors"
|
19
|
+
log.item "Detected pattern : #{result[:pattern]}"
|
20
|
+
log.item "Nb lines = #{result[:lines]}"
|
21
|
+
elsif result[:status] == :missing then
|
22
|
+
log.ko "Log : #{result[:log]} : missing !"
|
23
|
+
log.item "Detected pattern : #{result[:pattern]}"
|
24
|
+
else
|
25
|
+
log.ko "Log : #{result[:log]} : #{result[:count]} errors"
|
26
|
+
log.item "Detected pattern : #{result[:pattern]}"
|
27
|
+
log.item "Nb lines = #{result[:lines]}"
|
28
|
+
end
|
29
|
+
|
22
30
|
full_status = false unless result[:status] == :clean
|
23
31
|
end
|
24
32
|
display_status = (full_status)? "OK": "KO"
|
25
|
-
|
33
|
+
if full_status then
|
34
|
+
log.ok "Global status : no error found"
|
35
|
+
else
|
36
|
+
log.error "Global status : some error found"
|
37
|
+
end
|
26
38
|
splash_exit case: :quiet_exit
|
27
39
|
end
|
28
40
|
|
@@ -36,32 +48,34 @@ module CLISplash
|
|
36
48
|
end
|
37
49
|
|
38
50
|
desc "show LOG", "show configured log monitoring for LOG"
|
39
|
-
def show(
|
40
|
-
|
51
|
+
def show(logrecord)
|
52
|
+
log = get_logger
|
53
|
+
log_record_set = get_config.logs.select{|item| item[:log] == logrecord }
|
41
54
|
unless log_record_set.empty? then
|
42
55
|
record = log_record_set.first
|
43
|
-
|
44
|
-
|
56
|
+
log.info "Splash log monitor : #{record[:log]}"
|
57
|
+
log.item "pattern : /#{record[:pattern]}/"
|
45
58
|
splash_exit case: :quiet_exit
|
46
|
-
|
59
|
+
else
|
47
60
|
splash_exit case: :not_found, :more => "log not configured"
|
48
61
|
end
|
49
62
|
end
|
50
63
|
|
51
64
|
desc "list", "Show configured logs monitoring"
|
52
65
|
long_desc <<-LONGDESC
|
53
|
-
Show configured logs monitoring
|
66
|
+
Show configured logs monitoring\n
|
54
67
|
with --detail, show logs monitor details
|
55
68
|
LONGDESC
|
56
69
|
option :detail, :type => :boolean
|
57
70
|
def list
|
58
|
-
|
71
|
+
log = get_logger
|
72
|
+
log.info "Splash configured log monitoring :"
|
59
73
|
log_record_set = get_config.logs
|
60
|
-
|
74
|
+
log.ko 'No configured commands found' if log_record_set.empty?
|
61
75
|
log_record_set.each do |record|
|
62
|
-
|
76
|
+
log.item "log monitor : #{record[:log]}"
|
63
77
|
if options[:detail] then
|
64
|
-
|
78
|
+
log.flat " -> pattern : /#{record[:pattern]}/"
|
65
79
|
end
|
66
80
|
end
|
67
81
|
splash_exit case: :quiet_exit
|
data/lib/splash/commands.rb
CHANGED
@@ -25,7 +25,7 @@ module Splash
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def ack
|
28
|
-
|
28
|
+
get_logger.info "Sending ack for command : '#{@name}'"
|
29
29
|
notify(0,0)
|
30
30
|
end
|
31
31
|
|
@@ -37,17 +37,18 @@ module Splash
|
|
37
37
|
@@metric_time.set(time)
|
38
38
|
hostname = Socket.gethostname
|
39
39
|
Prometheus::Client::Push.new(@name, hostname, @url).add(@@registry)
|
40
|
-
|
40
|
+
get_logger.ok "Prometheus Gateway notified."
|
41
41
|
return { :case => :quiet_exit}
|
42
42
|
end
|
43
43
|
|
44
44
|
|
45
45
|
def call_and_notify(options)
|
46
|
+
log = get_logger
|
46
47
|
acase = { :case => :quiet_exit }
|
47
48
|
exit_code = 0
|
48
49
|
if @config.commands[@name.to_sym][:delegate_to] then
|
49
50
|
return { :case => :options_incompatibility, :more => '--hostname forbidden with delagate commands'} if options[:hostname]
|
50
|
-
|
51
|
+
log.send "Remote command : #{@name} execution delegate to : #{@config.commands[@name.to_sym][:delegate_to][:host]} as : #{@config.commands[@name.to_sym][:delegate_to][:remote_command]}"
|
51
52
|
begin
|
52
53
|
transport = get_default_client
|
53
54
|
if transport.class == Hash and transport.include? :case then
|
@@ -58,18 +59,18 @@ module Splash
|
|
58
59
|
:return_to => "splash.#{Socket.gethostname}.return",
|
59
60
|
:queue => "splash.#{@config.commands[@name.to_sym][:delegate_to][:host]}.input" })
|
60
61
|
exit_code = res[:exit_code]
|
61
|
-
|
62
|
+
log.receive "return with exitcode #{exit_code}"
|
62
63
|
|
63
64
|
end
|
64
65
|
end
|
65
66
|
else
|
66
|
-
|
67
|
+
log.info "Executing command : '#{@name}' "
|
67
68
|
start = Time.now
|
68
69
|
start_date = DateTime.now.to_s
|
69
70
|
unless options[:trace] then
|
70
|
-
|
71
|
+
log.item "Traceless execution"
|
71
72
|
if @config.commands[@name.to_sym][:user] then
|
72
|
-
|
73
|
+
log.item "Execute with user : #{@config.commands[@name.to_sym][:user]}."
|
73
74
|
system("sudo -u #{@config.commands[@name.to_sym][:user]} #{@config.commands[@name.to_sym][:command]} > /dev/null 2>&1")
|
74
75
|
else
|
75
76
|
system("#{@config.commands[@name.to_sym][:command]} > /dev/null 2>&1")
|
@@ -77,9 +78,9 @@ module Splash
|
|
77
78
|
time = Time.now - start
|
78
79
|
exit_code = $?.exitstatus
|
79
80
|
else
|
80
|
-
|
81
|
+
log.item "Tracefull execution"
|
81
82
|
if @config.commands[@name.to_sym][:user] then
|
82
|
-
|
83
|
+
log.item "Execute with user : #{@config.commands[@name.to_sym][:user]}."
|
83
84
|
stdout, stderr, status = Open3.capture3("sudo -u #{@config.commands[@name.to_sym][:user]} #{@config.commands[@name.to_sym][:command]}")
|
84
85
|
else
|
85
86
|
stdout, stderr, status = Open3.capture3(@config.commands[@name.to_sym][:command])
|
@@ -103,12 +104,12 @@ module Splash
|
|
103
104
|
backend.put key: key, value: data.to_yaml
|
104
105
|
exit_code = status.exitstatus
|
105
106
|
end
|
106
|
-
|
107
|
-
|
107
|
+
log.ok "Command executed"
|
108
|
+
log.arrow "exitcode #{exit_code}"
|
108
109
|
if options[:notify] then
|
109
110
|
acase = notify(exit_code,time.to_i)
|
110
111
|
else
|
111
|
-
|
112
|
+
log.item "Without Prometheus notification"
|
112
113
|
end
|
113
114
|
end
|
114
115
|
|
@@ -116,7 +117,7 @@ module Splash
|
|
116
117
|
on_failure = (@config.commands[@name.to_sym][:on_failure])? @config.commands[@name.to_sym][:on_failure] : false
|
117
118
|
on_success = (@config.commands[@name.to_sym][:on_success])? @config.commands[@name.to_sym][:on_success] : false
|
118
119
|
if on_failure and exit_code > 0 then
|
119
|
-
|
120
|
+
log.item "On failure callback : #{on_failure}"
|
120
121
|
if @config.commands.keys.include? on_failure then
|
121
122
|
@name = on_failure.to_s
|
122
123
|
call_and_notify options
|
@@ -125,16 +126,16 @@ module Splash
|
|
125
126
|
end
|
126
127
|
end
|
127
128
|
if on_success and exit_code == 0 then
|
128
|
-
|
129
|
+
log.item "On success callback : #{on_success}"
|
129
130
|
if @config.commands.keys.include? on_success then
|
130
131
|
@name = on_success.to_s
|
131
132
|
call_and_notify options
|
132
133
|
else
|
133
|
-
|
134
|
+
acase = { :case => :configuration_error , :more => "on_success call error : #{on_failure} command inexistant."}
|
134
135
|
end
|
135
136
|
end
|
136
137
|
else
|
137
|
-
|
138
|
+
log.item "Without callbacks sequences"
|
138
139
|
end
|
139
140
|
acase[:exit_code] = exit_code
|
140
141
|
return acase
|
data/lib/splash/config.rb
CHANGED
@@ -31,6 +31,7 @@ module Splash
|
|
31
31
|
|
32
32
|
self[:transports] = {} ; self[:transports].merge! TRANSPORTS_STRUCT ; self[:transports].merge! config_from_file[:transports] if config_from_file[:transports]
|
33
33
|
self[:backends] = {} ; self[:backends].merge! BACKENDS_STRUCT ; self[:backends].merge! config_from_file[:backends] if config_from_file[:backends]
|
34
|
+
self[:loggers] = {} ; self[:loggers].merge! LOGGERS_STRUCT ; self[:loggers].merge! config_from_file[:loggers] if config_from_file[:loggers]
|
34
35
|
|
35
36
|
self[:logs] = (config_from_file[:logs])? config_from_file[:logs] : {}
|
36
37
|
self[:commands] = (config_from_file[:commands])? config_from_file[:commands] : {}
|
@@ -39,6 +40,9 @@ module Splash
|
|
39
40
|
|
40
41
|
# @!group accessors on configurations Items
|
41
42
|
|
43
|
+
def loggers
|
44
|
+
return self[:loggers]
|
45
|
+
end
|
42
46
|
|
43
47
|
def backends
|
44
48
|
return self[:backends]
|
@@ -3,53 +3,57 @@ module Splash
|
|
3
3
|
module ConfigUtilities
|
4
4
|
include Splash::Constants
|
5
5
|
|
6
|
+
|
7
|
+
|
6
8
|
# Sanitycheck action method for testing installation of Splash
|
7
9
|
# @return [Integer] an errorcode value
|
8
|
-
def checkconfig
|
9
|
-
|
10
|
+
def checkconfig(options ={})
|
11
|
+
self.extend Splash::Loggers
|
12
|
+
log = get_logger
|
13
|
+
log.info "Splash -> sanitycheck : "
|
10
14
|
config = get_config
|
11
15
|
full_res = 0
|
12
|
-
print "* Config file : #{CONFIG_FILE} : "
|
13
16
|
res = verify_file(name: CONFIG_FILE, mode: "644", owner: config.user_root, group: config.group_root)
|
17
|
+
target = "Config file : #{CONFIG_FILE}"
|
14
18
|
if res.empty? then
|
15
|
-
|
19
|
+
log.ok target
|
16
20
|
else
|
17
|
-
|
21
|
+
log.ko target
|
18
22
|
full_res =+ 1
|
19
|
-
|
23
|
+
log.flat " pbm => #{res.map {|p| p.to_s}.join(',')}"
|
20
24
|
end
|
21
25
|
|
22
|
-
|
26
|
+
target = "PID Path : #{config[:pid_path]}"
|
23
27
|
res = verify_folder(name: config[:pid_path], mode: "644", owner: config.user_root, group: config.group_root)
|
24
28
|
if res.empty? then
|
25
|
-
|
29
|
+
log.ok target
|
26
30
|
else
|
27
|
-
|
31
|
+
log.ko target
|
28
32
|
full_res =+ 1
|
29
|
-
|
33
|
+
log.flat " pbm => #{res.map {|p| p.to_s}.join(',')}"
|
30
34
|
|
31
35
|
end
|
32
36
|
|
33
|
-
|
34
|
-
res = verify_folder(name: config[:trace_path], mode: "
|
37
|
+
target = "Trace Path : #{config[:trace_path]}"
|
38
|
+
res = verify_folder(name: config[:trace_path], mode: "644", owner: config.user_root, group: config.group_root)
|
35
39
|
if res.empty? then
|
36
|
-
|
40
|
+
log.ok target
|
37
41
|
else
|
38
|
-
|
42
|
+
log.ko target
|
39
43
|
full_res =+ 1
|
40
|
-
|
44
|
+
log.flat " pbm => #{res.map {|p| p.to_s}.join(',')}"
|
41
45
|
end
|
42
46
|
|
43
|
-
|
47
|
+
target = "Prometheus PushGateway Service running"
|
44
48
|
if verify_service host: config.prometheus_pushgateway_host ,port: config.prometheus_pushgateway_port then
|
45
|
-
|
49
|
+
log.ok target
|
46
50
|
else
|
47
|
-
|
51
|
+
log.ko target
|
48
52
|
full_res =+ 1
|
49
53
|
end
|
50
54
|
|
51
55
|
if full_res > 0 then
|
52
|
-
|
56
|
+
log.error "#{full_res} errors occured"
|
53
57
|
return { :case => :splash_sanitycheck_error }
|
54
58
|
else
|
55
59
|
return { :case => :splash_sanitycheck_success}
|
data/lib/splash/config/setup.rb
CHANGED
@@ -22,36 +22,40 @@ module Splash
|
|
22
22
|
puts "[KO]"
|
23
23
|
end
|
24
24
|
else
|
25
|
-
puts "Config file preservation."
|
25
|
+
puts "Config file preservation, verify your homemade templates."
|
26
26
|
end
|
27
27
|
config = get_config
|
28
|
+
self.extend Splash::Loggers
|
29
|
+
log = get_logger
|
30
|
+
log.ok "Splash Initialisation"
|
28
31
|
report_in_path = search_file_in_gem "prometheus-splash", "templates/report.txt"
|
29
|
-
|
32
|
+
target = "Installing template file : #{config.execution_template_path}"
|
30
33
|
if install_file source: report_in_path, target: config.execution_template_path, mode: "644", owner: config.user_root, group: config.group_root then
|
31
|
-
|
34
|
+
log.ok target
|
32
35
|
else
|
33
36
|
full_res =+ 1
|
34
|
-
|
37
|
+
log.ko target
|
35
38
|
end
|
36
39
|
|
37
|
-
|
40
|
+
target = "Creating/Checking pid file path : #{config[:pid_path]}"
|
38
41
|
if make_folder path: config[:pid_path], mode: "644", owner: config.user_root, group: config.group_root then
|
39
|
-
|
42
|
+
log.ok target
|
40
43
|
else
|
41
44
|
full_res =+ 1
|
42
|
-
|
45
|
+
log.ko target
|
43
46
|
end
|
44
47
|
|
45
|
-
|
48
|
+
target = "Creating/Checking trace file path : #{config[:trace_path]} : "
|
46
49
|
if make_folder path: config[:trace_path], mode: "644", owner: config.user_root, group: config.group_root then
|
47
|
-
|
50
|
+
log.ok target
|
48
51
|
else
|
49
52
|
full_res =+ 1
|
50
|
-
|
53
|
+
log.ko target
|
51
54
|
end
|
52
55
|
|
56
|
+
|
53
57
|
if full_res > 0 then
|
54
|
-
|
58
|
+
log.error "#{full_res} errors occured"
|
55
59
|
return { :case => :splash_setup_error}
|
56
60
|
else
|
57
61
|
return { :case => :splash_setup_success }
|
data/lib/splash/constants.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
module Splash
|
3
3
|
module Constants
|
4
|
-
VERSION = "0.
|
4
|
+
VERSION = "0.4.0"
|
5
5
|
|
6
6
|
# the path to th config file, not overridable by config
|
7
7
|
CONFIG_FILE = "/etc/splash.yml"
|
@@ -47,10 +47,14 @@ module Splash
|
|
47
47
|
:stores => { :execution_trace => { :type => :file, :path => "/var/run/splash" }}}
|
48
48
|
# transports default settings
|
49
49
|
TRANSPORTS_STRUCT = { :list => [:rabbitmq],
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
:active => :rabbitmq,
|
51
|
+
:rabbitmq => { :port => 5672, :host => "localhost", :vhost => '/'} }
|
52
|
+
|
53
|
+
LOGGERS_STRUCT = { :list => [:cli,:daemon, :dual],
|
54
|
+
:default => :cli,
|
55
|
+
:level => :info,
|
56
|
+
:daemon => {:file => '/var/log/splash.log'},
|
57
|
+
:cli => {:color => true, :emoji => true } }
|
54
58
|
|
55
59
|
end
|
56
60
|
end
|