prometheus-splash 0.0.3 → 0.1.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/README.md +642 -8
- data/assets/images/detail_prom_splash.png +0 -0
- data/assets/images/logo_splash.png +0 -0
- data/assets/images/logo_splash_reduce.png +0 -0
- data/assets/images/prom_pg_logs.png +0 -0
- data/bin/splash +98 -10
- data/config/splash.yml +2 -14
- data/lib/splash/backends/file.rb +11 -5
- data/lib/splash/backends/redis.rb +28 -6
- data/lib/splash/commands.rb +25 -20
- data/lib/splash/config.rb +11 -7
- data/lib/splash/constants.rb +22 -2
- data/lib/splash/logs.rb +7 -0
- data/lib/splash/orchestrator.rb +33 -1
- data/lib/splash/templates.rb +13 -2
- data/lib/splash/transports/rabbitmq.rb +23 -6
- data/lib/splash/transports.rb +3 -3
- data/prometheus-splash.gemspec +2 -1
- data/templates/report.txt +2 -1
- metadata +20 -2
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/bin/splash
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby -W:no-deprecated
|
2
|
-
|
2
|
+
require 'socket'
|
3
|
+
require 'yaml'
|
4
|
+
require 'thread'
|
3
5
|
|
4
6
|
begin
|
5
7
|
require 'prometheus/client'
|
@@ -20,6 +22,7 @@ require 'splash/helpers'
|
|
20
22
|
require 'splash/config'
|
21
23
|
require 'splash/templates'
|
22
24
|
require 'splash/backends'
|
25
|
+
require 'splash/transports'
|
23
26
|
|
24
27
|
require 'splash/commands'
|
25
28
|
require 'splash/logs'
|
@@ -38,21 +41,24 @@ module CLISplash
|
|
38
41
|
include Splash::Config
|
39
42
|
include Splash::Backends
|
40
43
|
|
41
|
-
desc "
|
44
|
+
desc "execute NAME", "run for command/sequence or ack result"
|
42
45
|
long_desc <<-LONGDESC
|
43
|
-
|
44
|
-
with --no-trace prevent storing execution trace in
|
46
|
+
execute command or sequence or ack result
|
47
|
+
with --no-trace prevent storing execution trace in configured backend (see config file)
|
45
48
|
with --ack, notify errorcode=0 to Prometheus PushGateway
|
46
49
|
with --no-notify, bypass Prometheus notification
|
50
|
+
with --no-callback, never execute callback (:on_failure, :on_success)
|
51
|
+
never follow sequences
|
47
52
|
LONGDESC
|
48
53
|
option :trace, :type => :boolean, :default => true
|
49
54
|
option :ack, :type => :boolean, negate: false
|
50
55
|
option :notify, :type => :boolean, :default => true
|
51
|
-
|
56
|
+
option :callback, :type => :boolean, :default => true
|
57
|
+
def execute(name)
|
52
58
|
if is_root? then
|
53
59
|
command = Splash::CommandWrapper::new(name)
|
54
60
|
command.ack if options[:ack]
|
55
|
-
command.call_and_notify trace: options[:trace], notify: options[:notify]
|
61
|
+
command.call_and_notify trace: options[:trace], notify: options[:notify], callback: options[:callback]
|
56
62
|
else
|
57
63
|
$stderr.puts "Command wrapping need to be run as root"
|
58
64
|
exit 60
|
@@ -124,14 +130,24 @@ module CLISplash
|
|
124
130
|
|
125
131
|
|
126
132
|
desc "lastrun COMMAND", "Show last running result for specific configured command COMMAND"
|
133
|
+
long_desc <<-LONGDESC
|
134
|
+
Show last running result for specific configured command COMMAND
|
135
|
+
with --hostname <HOSTNAME>, an other Splash monitored server (only with Redis backend configured)
|
136
|
+
LONGDESC
|
137
|
+
option :hostname, :type => :string
|
127
138
|
def lastrun(command)
|
139
|
+
backend = get_backend :execution_trace
|
140
|
+
redis = (backend.class == Splash::Backends::Redis)? true : false
|
141
|
+
if not redis and options[:hostname] then
|
142
|
+
$stderr.puts "Remote execution report request only possible with Redis backend"
|
143
|
+
end
|
128
144
|
list = get_config.commands
|
129
145
|
if list.keys.include? command.to_sym then
|
130
146
|
print "Splash command #{command} previous execution report:\n\n"
|
131
|
-
|
132
|
-
|
133
|
-
if backend.exist?
|
134
|
-
print backend.get
|
147
|
+
req = { :key => command}
|
148
|
+
req[:hostname] = options[:hostname] if options[:hostname]
|
149
|
+
if backend.exist? req then
|
150
|
+
print backend.get req
|
135
151
|
else
|
136
152
|
puts "Command not already runned."
|
137
153
|
end
|
@@ -141,11 +157,58 @@ module CLISplash
|
|
141
157
|
end
|
142
158
|
end
|
143
159
|
|
160
|
+
desc "getreportlist COMMAND", "list all executions report results "
|
161
|
+
long_desc <<-LONGDESC
|
162
|
+
Show configured commands
|
163
|
+
with --pattern <SEARCH>, search type string, wilcard * (group) ? (char)
|
164
|
+
with --hostname <HOSTNAME>, an other Splash monitored server (only with Redis backend configured)
|
165
|
+
with --all, get all execution report for all servers (only with Redis backend configured)
|
166
|
+
--all and --hostname are exclusives
|
167
|
+
LONGDESC
|
168
|
+
option :pattern, :type => :string
|
169
|
+
option :hostname, :type => :string
|
170
|
+
option :all, :type => :boolean, :negate => false
|
171
|
+
def getreportlist
|
172
|
+
if options[:hostname] and options[:all] then
|
173
|
+
$stderr.puts "--all option imcompatible with --hostname"
|
174
|
+
exit 40
|
175
|
+
end
|
176
|
+
backend = get_backend :execution_trace
|
177
|
+
redis = (backend.class == Splash::Backends::Redis)? true : false
|
178
|
+
if not redis and (options[:hostname] or options[:all]) then
|
179
|
+
$stderr.puts "Remote execution report request only possible with Redis backend"
|
180
|
+
exit 40
|
181
|
+
end
|
182
|
+
pattern = (options[:pattern])? options[:pattern] : '*'
|
183
|
+
if options[:all] then
|
184
|
+
res = backend.listall pattern
|
185
|
+
elsif options[:hostname]
|
186
|
+
res = backend.list pattern, options[:hostname]
|
187
|
+
else
|
188
|
+
res = backend.list pattern
|
189
|
+
end
|
190
|
+
print "List of Executions reports :\n\n"
|
191
|
+
puts "Not reports found" if res.empty?
|
192
|
+
res.each do |item|
|
193
|
+
if options[:all]
|
194
|
+
host,command = item.split('#')
|
195
|
+
puts " * Command : #{command} @ host : #{host}"
|
196
|
+
else
|
197
|
+
puts " * Command : #{item}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
|
144
204
|
end
|
145
205
|
|
146
206
|
|
207
|
+
|
208
|
+
|
147
209
|
class CLIController < Thor
|
148
210
|
include Splash::LogsMonitor::DaemonController
|
211
|
+
include Splash::Transports
|
149
212
|
|
150
213
|
option :foreground, :type => :boolean
|
151
214
|
desc "start", "Starting Logs Monitor Daemon"
|
@@ -166,6 +229,26 @@ module CLISplash
|
|
166
229
|
exit errorcode
|
167
230
|
end
|
168
231
|
|
232
|
+
desc "ping HOSTNAME", "send a ping to HOSTNAME daemon over transport (need an active tranport), Typicallly RabbitMQ"
|
233
|
+
def ping(hostname=Socket.gethostname)
|
234
|
+
puts "ctrl+c for interrupt"
|
235
|
+
queue = "splash.#{Socket.gethostname}.returncli"
|
236
|
+
order = {:verb => :ping, :payload => {:hostname => Socket.gethostname}, :return_to => queue}
|
237
|
+
|
238
|
+
lock = Mutex.new
|
239
|
+
condition = ConditionVariable.new
|
240
|
+
begin
|
241
|
+
get_default_subscriber(queue: queue).subscribe(timeout: 10) do |delivery_info, properties, payload|
|
242
|
+
puts YAML::load(payload)
|
243
|
+
lock.synchronize { condition.signal }
|
244
|
+
end
|
245
|
+
get_default_client.publish queue: "splash.#{hostname}.input", message: order.to_yaml
|
246
|
+
lock.synchronize { condition.wait(lock) }
|
247
|
+
rescue Interrupt
|
248
|
+
puts "Splash : ping : Interrupted by user. "
|
249
|
+
exit 33
|
250
|
+
end
|
251
|
+
end
|
169
252
|
|
170
253
|
end
|
171
254
|
|
@@ -177,6 +260,11 @@ module CLISplash
|
|
177
260
|
include Splash::Helpers
|
178
261
|
|
179
262
|
desc "setup", "Setup installation fo Splash"
|
263
|
+
long_desc <<-LONGDESC
|
264
|
+
Setup installation fo Splash
|
265
|
+
with --preserve, preserve from reinstallation of the config
|
266
|
+
LONGDESC
|
267
|
+
option :preserve, :type => :boolean
|
180
268
|
def setup
|
181
269
|
errorcode = run_as_root :setupsplash
|
182
270
|
exit errorcode
|
data/config/splash.yml
CHANGED
@@ -5,19 +5,7 @@
|
|
5
5
|
:templates:
|
6
6
|
:execution:
|
7
7
|
:path: /etc/splash_execution_report.tpl
|
8
|
-
:tokens:
|
9
|
-
- :date
|
10
|
-
- :cmd_name
|
11
|
-
- :cmd_line
|
12
|
-
- :stdout
|
13
|
-
- :stderr
|
14
|
-
- :desc
|
15
|
-
- :status
|
16
|
-
- :exec_time
|
17
8
|
:backends:
|
18
|
-
:list:
|
19
|
-
- :file
|
20
|
-
- :redis
|
21
9
|
:stores:
|
22
10
|
:execution_trace:
|
23
11
|
:type: :file
|
@@ -94,5 +82,5 @@
|
|
94
82
|
:logs:
|
95
83
|
- :log: /tmp/test
|
96
84
|
:pattern: ERROR
|
97
|
-
- :log: /
|
98
|
-
:pattern:
|
85
|
+
- :log: /tmp/test2
|
86
|
+
:pattern: ERROR
|
data/lib/splash/backends/file.rb
CHANGED
@@ -8,25 +8,31 @@ module Splash
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def list(pattern='*')
|
11
|
-
|
11
|
+
pattern = suffix_trace(pattern)
|
12
|
+
return Dir.glob("#{@path}/#{pattern}").map{|item| ::File.basename(item,".trace") }
|
12
13
|
end
|
13
14
|
|
14
15
|
def get(options)
|
15
|
-
return ::File.readlines("#{@path}/#{options[:key]}").join
|
16
|
+
return ::File.readlines("#{@path}/#{suffix_trace(options[:key])}").join
|
16
17
|
end
|
17
18
|
|
18
19
|
def put(options)
|
19
|
-
::File.open("#{@path}/#{options[:key]}", 'w') { |file|
|
20
|
+
::File.open("#{@path}/#{suffix_trace(options[:key])}", 'w') { |file|
|
20
21
|
file.write options[:value]
|
21
22
|
}
|
22
23
|
end
|
23
24
|
|
24
25
|
def del(options)
|
25
|
-
::File.unlink("#{@path}/#{options[:key]}") if File.exist?("#{@path}/#{options[:key]}")
|
26
|
+
::File.unlink("#{@path}/#{suffix_trace(options[:key])}") if File.exist?("#{@path}/#{suffix_trace(options[:key])}")
|
26
27
|
end
|
27
28
|
|
28
29
|
def exist?(options)
|
29
|
-
return ::File.exist?("#{@path}/#{options[:key]}")
|
30
|
+
return ::File.exist?("#{@path}/#{suffix_trace(options[:key])}")
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def suffix_trace(astring)
|
35
|
+
return "#{astring}.trace"
|
30
36
|
end
|
31
37
|
|
32
38
|
end
|
@@ -1,30 +1,39 @@
|
|
1
1
|
require "redis"
|
2
|
+
require "socket"
|
2
3
|
|
3
4
|
module Splash
|
4
5
|
module Backends
|
5
6
|
class Redis
|
6
7
|
include Splash::Config
|
7
8
|
def initialize(store)
|
9
|
+
@hostname = Socket.gethostname
|
8
10
|
@config = get_config[:backends][:stores][store]
|
9
11
|
@store = ::Redis.new :host => @config[:host], :port => @config[:port], :db => @config[:base].to_i
|
10
12
|
@redis_cli_cmd = `which redis-cli`
|
11
13
|
@store.auth(@config[:auth]) if @config[:auth]
|
12
14
|
end
|
13
15
|
|
14
|
-
def list(pattern='*')
|
15
|
-
return @store.keys
|
16
|
+
def list(pattern='*', hostname = @hostname)
|
17
|
+
return @store.keys("#{hostname}##{pattern}").map{|item| item = remove_hostname(item)}
|
18
|
+
end
|
19
|
+
|
20
|
+
def listall(pattern='*')
|
21
|
+
return @store.keys(pattern)
|
16
22
|
end
|
17
23
|
|
18
24
|
def get(options)
|
19
|
-
|
25
|
+
hostname = (options[:hostname])? options[:hostname] : @hostname
|
26
|
+
return @store.get(prefix_hostname(options[:key],hostname))
|
20
27
|
end
|
21
28
|
|
22
29
|
def put(options)
|
23
|
-
|
30
|
+
hostname = (options[:hostname])? options[:hostname] : @hostname
|
31
|
+
@store.set prefix_hostname(options[:key],hostname), options[:value]
|
24
32
|
end
|
25
33
|
|
26
34
|
def del(options)
|
27
|
-
|
35
|
+
hostname = (options[:hostname])? options[:hostname] : @hostname
|
36
|
+
@store.del prefix_hostname(options[:key],hostname)
|
28
37
|
end
|
29
38
|
|
30
39
|
def flush
|
@@ -33,7 +42,20 @@ module Splash
|
|
33
42
|
end
|
34
43
|
|
35
44
|
def exist?(options)
|
36
|
-
|
45
|
+
hostname = (options[:hostname])? options[:hostname] : @hostname
|
46
|
+
return ( not @store.get(prefix_hostname(options[:key],hostname)).nil?)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def prefix_hostname(key,hostname)
|
51
|
+
return "#{hostname}##{key}"
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def remove_hostname(astring)
|
56
|
+
result = astring.split("#")
|
57
|
+
result.shift
|
58
|
+
return result.join("#")
|
37
59
|
end
|
38
60
|
|
39
61
|
end
|
data/lib/splash/commands.rb
CHANGED
@@ -47,6 +47,7 @@ module Splash
|
|
47
47
|
def call_and_notify(options)
|
48
48
|
puts "Executing command : '#{@name}' "
|
49
49
|
start = Time.now
|
50
|
+
start_date = DateTime.now.to_s
|
50
51
|
unless options[:trace] then
|
51
52
|
puts " * Traceless execution"
|
52
53
|
if @config.commands[@name.to_sym][:user] then
|
@@ -70,7 +71,8 @@ module Splash
|
|
70
71
|
list_token: @config.execution_template_tokens,
|
71
72
|
template_file: @config.execution_template_path)
|
72
73
|
|
73
|
-
tp.
|
74
|
+
tp.start_date = start_date
|
75
|
+
tp.end_date = DateTime.now.to_s
|
74
76
|
tp.cmd_name = @name
|
75
77
|
tp.cmd_line = @config.commands[@name.to_sym][:command]
|
76
78
|
tp.desc = @config.commands[@name.to_sym][:desc]
|
@@ -79,7 +81,7 @@ module Splash
|
|
79
81
|
tp.stderr = stderr
|
80
82
|
tp.exec_time = time.to_s
|
81
83
|
backend = get_backend :execution_trace
|
82
|
-
key =
|
84
|
+
key = @name
|
83
85
|
backend.put key: key, value: tp.output
|
84
86
|
exit_code = status.exitstatus
|
85
87
|
|
@@ -91,29 +93,32 @@ module Splash
|
|
91
93
|
else
|
92
94
|
puts " * Without Prometheus notification"
|
93
95
|
end
|
94
|
-
|
95
|
-
|
96
|
+
if options[:callback] then
|
97
|
+
on_failure = (@config.commands[@name.to_sym][:on_failure])? @config.commands[@name.to_sym][:on_failure] : false
|
98
|
+
on_success = (@config.commands[@name.to_sym][:on_success])? @config.commands[@name.to_sym][:on_success] : false
|
96
99
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
100
|
+
if on_failure and exit_code > 0 then
|
101
|
+
puts " * On failure callback : #{on_failure}"
|
102
|
+
if @config.commands.keys.include? on_failure then
|
103
|
+
@name = on_failure.to_s
|
104
|
+
call_and_notify options
|
105
|
+
else
|
106
|
+
$stderr.puts "on_failure call error : configuration mistake : #{on_failure} command inexistant."
|
107
|
+
end
|
104
108
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
109
|
+
if on_success and exit_code == 0 then
|
110
|
+
puts " * On success callback : #{on_success}"
|
111
|
+
if @config.commands.keys.include? on_success then
|
112
|
+
@name = on_success.to_s
|
113
|
+
call_and_notify options
|
114
|
+
else
|
115
|
+
$stderr.puts "on_success call error : configuration mistake : #{on_success} command inexistant."
|
116
|
+
end
|
113
117
|
end
|
118
|
+
else
|
119
|
+
puts " * Without callbacks sequences"
|
114
120
|
end
|
115
121
|
|
116
|
-
|
117
122
|
exit exit_code
|
118
123
|
end
|
119
124
|
end
|
data/lib/splash/config.rb
CHANGED
@@ -18,7 +18,7 @@ module Splash
|
|
18
18
|
self[:prometheus_pushgateway_port] = (config_from_file[:prometheus][:pushgateway][:port])? config_from_file[:prometheus][:pushgateway][:port] : PROMETHEUS_PUSHGATEWAY_PORT
|
19
19
|
self[:daemon_process_name] = (config_from_file[:daemon][:process_name])? config_from_file[:daemon][:process_name] : DAEMON_PROCESS_NAME
|
20
20
|
self[:daemon_logmon_scheduling] = (config_from_file[:daemon][:logmon_scheduling])? config_from_file[:daemon][:logmon_scheduling] : DAEMON_LOGMON_SCHEDULING
|
21
|
-
self[:execution_template_tokens] =
|
21
|
+
self[:execution_template_tokens] = EXECUTION_TEMPLATE_TOKENS_LIST
|
22
22
|
self[:execution_template_path] = (config_from_file[:templates][:execution][:path])? config_from_file[:templates][:execution][:path] : EXECUTION_TEMPLATE
|
23
23
|
self[:pid_path] = (config_from_file[:daemon][:paths][:pid_path])? config_from_file[:daemon][:paths][:pid_path] : DAEMON_PID_PATH
|
24
24
|
self[:trace_path] = (config_from_file[:daemon][:paths][:trace_path])? config_from_file[:daemon][:paths][:trace_path] : TRACE_PATH
|
@@ -58,7 +58,7 @@ module Splash
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def transports
|
61
|
-
return self[:
|
61
|
+
return self[:transports]
|
62
62
|
end
|
63
63
|
|
64
64
|
def daemon_logmon_scheduling
|
@@ -137,12 +137,16 @@ module Splash
|
|
137
137
|
conf_in_path = search_file_in_gem "prometheus-splash", "config/splash.yml"
|
138
138
|
full_res = 0
|
139
139
|
puts "Splash -> setup : "
|
140
|
-
|
141
|
-
|
142
|
-
|
140
|
+
unless options[:preserve] then
|
141
|
+
print "* Installing Configuration file : #{CONFIG_FILE} : "
|
142
|
+
if install_file source: conf_in_path, target: CONFIG_FILE, mode: "644", owner: Configuration.user_root, group: Configuration.group_root then
|
143
|
+
puts "[OK]"
|
144
|
+
else
|
145
|
+
full_res =+ 1
|
146
|
+
puts "[KO]"
|
147
|
+
end
|
143
148
|
else
|
144
|
-
|
145
|
-
puts "[KO]"
|
149
|
+
puts "Config file preservation."
|
146
150
|
end
|
147
151
|
config = get_config
|
148
152
|
report_in_path = search_file_in_gem "prometheus-splash", "templates/report.txt"
|
data/lib/splash/constants.rb
CHANGED
@@ -1,30 +1,50 @@
|
|
1
1
|
module Splash
|
2
2
|
module Constants
|
3
|
-
VERSION = "0.0
|
3
|
+
VERSION = "0.1.0"
|
4
4
|
|
5
|
+
# the path to th config file, not overridable by config
|
5
6
|
CONFIG_FILE = "/etc/splash.yml"
|
7
|
+
# the default execution trace_path if backend file
|
6
8
|
TRACE_PATH="/var/run/splash"
|
7
9
|
|
10
|
+
|
11
|
+
# default scheduling criteria for log monitoring
|
8
12
|
DAEMON_LOGMON_SCHEDULING={ :every => '20s'}
|
13
|
+
# the display name of daemon in proc info (ps/top)
|
9
14
|
DAEMON_PROCESS_NAME="Splash : daemon."
|
15
|
+
# the default pid file path
|
10
16
|
DAEMON_PID_PATH="/var/run"
|
17
|
+
# the default pid file name
|
11
18
|
DAEMON_PID_FILE="splash.pid"
|
19
|
+
# the default sdtout trace file
|
12
20
|
DAEMON_STDOUT_TRACE="stdout.txt"
|
21
|
+
# the default sdterr trace file
|
13
22
|
DAEMON_STDERR_TRACE="stderr.txt"
|
14
23
|
|
24
|
+
# the Author name
|
15
25
|
AUTHOR="Romain GEORGES"
|
26
|
+
# the maintainer mail
|
16
27
|
EMAIL = "gems@ultragreen.net"
|
28
|
+
# legal Copyright (c) 2020 Copyright Utragreen All Rights Reserved.
|
17
29
|
COPYRIGHT="Ultragreen (c) 2020"
|
30
|
+
# type of licence
|
18
31
|
LICENSE="BSD-2-Clause"
|
19
32
|
|
33
|
+
# the default prometheus pushgateway host
|
20
34
|
PROMETHEUS_PUSHGATEWAY_HOST = "localhost"
|
35
|
+
# the default prometheus pushgateway port
|
21
36
|
PROMETHEUS_PUSHGATEWAY_PORT = "9091"
|
22
37
|
|
38
|
+
# the default path fo execution report template
|
23
39
|
EXECUTION_TEMPLATE="/etc/splash_execution_report.tpl"
|
24
|
-
EXECUTION_TEMPLATE_TOKENS_LIST = [:date,:cmd_name,:cmd_line,:stdout,:stderr,:desc,:status,:exec_time]
|
25
40
|
|
41
|
+
# the list of authorized tokens for template, carefull override,
|
42
|
+
EXECUTION_TEMPLATE_TOKENS_LIST = [:end_date,:start_date,:cmd_name,:cmd_line,:stdout,:stderr,:desc,:status,:exec_time]
|
43
|
+
|
44
|
+
# backends default settings
|
26
45
|
BACKENDS_STRUCT = { :list => [:file,:redis],
|
27
46
|
:stores => { :execution_trace => { :type => :file, :path => "/var/run/splash" }}}
|
47
|
+
# transports default settings
|
28
48
|
TRANSPORTS_STRUCT = { :list => [:rabbitmq],
|
29
49
|
:active => :rabbitmq,
|
30
50
|
:rabbitmq => { :url => 'amqp://localhost/'} }
|