prometheus-splash 0.7.0 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -1
  3. data/README.md +400 -178
  4. data/config/splash.yml +45 -5
  5. data/lib/splash/backends.rb +8 -1
  6. data/lib/splash/backends/file.rb +1 -1
  7. data/lib/splash/cli.rb +2 -1
  8. data/lib/splash/cli/commands.rb +100 -16
  9. data/lib/splash/cli/config.rb +12 -1
  10. data/lib/splash/cli/daemon.rb +41 -1
  11. data/lib/splash/cli/logs.rb +144 -48
  12. data/lib/splash/cli/process.rb +145 -52
  13. data/lib/splash/cli/transfers.rb +213 -0
  14. data/lib/splash/cli/webadmin.rb +3 -3
  15. data/lib/splash/commands.rb +85 -19
  16. data/lib/splash/config.rb +145 -52
  17. data/lib/splash/config/flush.rb +2 -2
  18. data/lib/splash/constants.rb +7 -3
  19. data/lib/splash/daemon/metrics.rb +6 -6
  20. data/lib/splash/daemon/orchestrator.rb +76 -36
  21. data/lib/splash/daemon/orchestrator/grammar.rb +16 -1
  22. data/lib/splash/dependencies.rb +6 -1
  23. data/lib/splash/exiter.rb +1 -1
  24. data/lib/splash/helpers.rb +12 -3
  25. data/lib/splash/loggers/cli.rb +2 -10
  26. data/lib/splash/logs.rb +94 -16
  27. data/lib/splash/processes.rb +91 -16
  28. data/lib/splash/transfers.rb +229 -0
  29. data/lib/splash/webadmin.rb +3 -3
  30. data/lib/splash/webadmin/api/routes/commands.rb +2 -2
  31. data/lib/splash/webadmin/api/routes/config.rb +95 -2
  32. data/lib/splash/webadmin/api/routes/logs.rb +32 -17
  33. data/lib/splash/webadmin/api/routes/process.rb +21 -9
  34. data/lib/splash/webadmin/api/routes/sequences.rb +2 -2
  35. data/lib/splash/webadmin/main.rb +3 -0
  36. data/lib/splash/webadmin/portal/controllers/commands.rb +2 -0
  37. data/lib/splash/webadmin/portal/controllers/documentation.rb +2 -0
  38. data/lib/splash/webadmin/portal/controllers/home.rb +24 -0
  39. data/lib/splash/webadmin/portal/controllers/logs.rb +57 -1
  40. data/lib/splash/webadmin/portal/controllers/processes.rb +61 -3
  41. data/lib/splash/webadmin/portal/controllers/proxy.rb +12 -3
  42. data/lib/splash/webadmin/portal/controllers/restclient.rb +6 -1
  43. data/lib/splash/webadmin/portal/controllers/sequences.rb +2 -0
  44. data/lib/splash/webadmin/portal/public/css/ultragreen.css +6 -0
  45. data/lib/splash/webadmin/portal/public/favicon.ico +0 -0
  46. data/lib/splash/webadmin/portal/views/commands.slim +1 -1
  47. data/lib/splash/webadmin/portal/views/documentation.slim +1 -1
  48. data/lib/splash/webadmin/portal/views/home.slim +53 -9
  49. data/lib/splash/webadmin/portal/views/layout.slim +2 -2
  50. data/lib/splash/webadmin/portal/views/log_form.slim +24 -0
  51. data/lib/splash/webadmin/portal/views/log_history.slim +24 -0
  52. data/lib/splash/webadmin/portal/views/logs.slim +93 -21
  53. data/lib/splash/webadmin/portal/views/nav.slim +1 -1
  54. data/lib/splash/webadmin/portal/views/not_found.slim +1 -1
  55. data/lib/splash/webadmin/portal/views/process_form.slim +21 -0
  56. data/lib/splash/webadmin/portal/views/process_history.slim +24 -0
  57. data/lib/splash/webadmin/portal/views/processes.slim +73 -3
  58. data/lib/splash/webadmin/portal/views/proxy.slim +5 -2
  59. data/lib/splash/webadmin/portal/views/restclient.slim +7 -4
  60. data/lib/splash/webadmin/portal/views/restclient_result.slim +24 -20
  61. data/lib/splash/webadmin/portal/views/sequences.slim +1 -1
  62. data/prometheus-splash.gemspec +7 -4
  63. data/ultragreen_roodi_coding_convention.yml +4 -4
  64. metadata +71 -8
@@ -32,20 +32,69 @@ module Splash
32
32
  def initialize(options = {})
33
33
  @log = get_logger
34
34
  self.extend Splash::Daemon::Metrics
35
- @metric_manager = get_metrics_manager
35
+ @session = get_session
36
+ @metric_manager = get_metrics_manager(@session)
36
37
  $stdout.sync = true
37
38
  $stderr.sync = true
38
39
  @server = Rufus::Scheduler::new
39
40
  @server.extend SchedulerHooks
40
41
  @config = get_config
42
+ @scheduling = options[:scheduling]
41
43
 
42
44
  @log.info "Splash Orchestrator starting :"
43
- if options[:scheduling] then
44
- @log.item "Initializing commands Scheduling."
45
+ if @scheduling then
46
+ @log.item "Initializing Sequences & commands Scheduling."
45
47
  init_commands_scheduling
46
48
  init_sequences_scheduling
47
49
  end
48
50
 
51
+ init_logs_monitoring_scheduling
52
+ init_process_monitoring_scheduling
53
+ init_metrics_scheduling
54
+ init_daemon_subscriber
55
+
56
+ end
57
+
58
+
59
+
60
+
61
+
62
+ # Stop the Splash daemon gracefully
63
+ # @return [hash] Exiter Case :quiet_exit
64
+ def terminate
65
+ @log.info "Splash daemon shutdown"
66
+ @server.shutdown
67
+ change_logger logger: :cli
68
+ splash_exit case: :quiet_exit
69
+ end
70
+
71
+ private
72
+
73
+ #prepare main daemon subscriber
74
+ def init_daemon_subscriber
75
+ hostname = Socket.gethostname
76
+ transport = get_default_subscriber queue: "splash.#{hostname}.input"
77
+ if transport.class == Hash and transport.include? :case then
78
+ splash_exit transport
79
+ end
80
+ transport.subscribe(:block => true) do |delivery_info, properties, body|
81
+ content = YAML::load(body)
82
+ session = get_session
83
+ content[:session] = session
84
+ if VERBS.include? content[:verb]
85
+ @log.receive "Valid remote order, verb : #{content[:verb].to_s}", session
86
+ res = self.send content[:verb], content
87
+ get_default_client.publish queue: content[:return_to], message: res.to_yaml
88
+ @log.send "Result to #{content[:return_to]}.", session
89
+ else
90
+ @log.receive "INVALID remote order, verb : #{content[:verb].to_s}", session
91
+ get_default_client.publish queue: content[:return_to], message: "Unkown verb #{content[:verb]}".to_yaml
92
+ end
93
+ end
94
+ end
95
+
96
+ #prepare logs monitoring sheduling
97
+ def init_logs_monitoring_scheduling
49
98
  if @config.logs.empty? then
50
99
  @log.item "No logs to monitor"
51
100
  else
@@ -64,7 +113,10 @@ module Splash
64
113
  end
65
114
  end
66
115
  end
116
+ end
67
117
 
118
+ #prepare process monitoring sheduling
119
+ def init_process_monitoring_scheduling
68
120
  if @config.processes.empty? then
69
121
  @log.item "No processes to monitor"
70
122
  else
@@ -83,49 +135,24 @@ module Splash
83
135
  end
84
136
  end
85
137
  end
138
+ end
86
139
 
87
140
 
141
+ #prepare metrics sheduling
142
+ def init_metrics_scheduling
88
143
  sched,value = @config.daemon_metrics_scheduling.flatten
89
144
  @log.item "Initializing Splash metrics notifications."
90
145
  @server.send sched,value do
91
146
  begin
147
+ @log.trigger "Splash Metrics monitoring for Scheduling : #{sched.to_s} #{value.to_s}", @session
92
148
  @metric_manager.notify
93
149
  rescue Errno::ECONNREFUSED
94
150
  @log.error "PushGateway seems to be done, please start it."
95
151
  end
96
152
  end
97
-
98
- hostname = Socket.gethostname
99
- transport = get_default_subscriber queue: "splash.#{hostname}.input"
100
- if transport.class == Hash and transport.include? :case then
101
- splash_exit transport
102
- end
103
- transport.subscribe(:block => true) do |delivery_info, properties, body|
104
- content = YAML::load(body)
105
- session = get_session
106
- content[:session] = session
107
- if VERBS.include? content[:verb]
108
- @log.receive "Valid remote order, verb : #{content[:verb].to_s}", session
109
- res = self.send content[:verb], content
110
- get_default_client.publish queue: content[:return_to], message: res.to_yaml
111
- @log.send "Result to #{content[:return_to]}.", session
112
- else
113
- @log.receive "INVALID remote order, verb : #{content[:verb].to_s}", session
114
- get_default_client.publish queue: content[:return_to], message: "Unkown verb #{content[:verb]}".to_yaml
115
- end
116
- end
117
153
  end
118
154
 
119
- # Stop the Splash daemon gracefully
120
- # @return [hash] Exiter Case :quiet_exit
121
- def terminate
122
- @log.info "Splash daemon shutdown"
123
- @server.shutdown
124
- change_logger logger: :cli
125
- splash_exit case: :quiet_exit
126
- end
127
155
 
128
- private
129
156
  # prepare commands Scheduling
130
157
  def init_commands_scheduling
131
158
  config = get_config.commands
@@ -139,7 +166,6 @@ module Splash
139
166
  execute command: command.to_s, session: session
140
167
  end
141
168
  end
142
-
143
169
  end
144
170
 
145
171
 
@@ -156,9 +182,25 @@ module Splash
156
182
  run_seq name: sequence.to_s, session: session
157
183
  end
158
184
  end
159
-
160
185
  end
161
186
 
187
+ # reset the orchestrator
188
+ # @return [Hash] Exiter case
189
+ def reset_orchestrator
190
+ @server.shutdown
191
+ @server = Rufus::Scheduler::new
192
+ @server.extend SchedulerHooks
193
+ @config = rehash_config
194
+ @log.info "Splash Orchestrator re-hashing :"
195
+ if @scheduling then
196
+ @log.item "Re-Initializing Sequences & commands Scheduling."
197
+ init_commands_scheduling
198
+ init_sequences_scheduling
199
+ end
200
+ init_logs_monitoring_scheduling
201
+ init_process_monitoring_scheduling
202
+ init_metrics_scheduling
203
+ end
162
204
 
163
205
 
164
206
  # execute_command verb : execute command specified in payload
@@ -174,9 +216,7 @@ module Splash
174
216
  return command.call_and_notify trace: true, notify: true, callback: true, session: options[:session]
175
217
  end
176
218
  end
177
-
178
219
  end
179
-
180
220
  end
181
221
  end
182
222
  end
@@ -16,7 +16,7 @@ module Splash
16
16
  include Splash::Loggers
17
17
 
18
18
  # list of known verbs for Splash orchestrator
19
- VERBS=[:ping,:list_commands,:execute_command,:ack_command, :shutdown]
19
+ VERBS=[:ping,:list_commands,:execute_command,:ack_command, :shutdown, :get_jobs, :reset]
20
20
 
21
21
  # shutdown verb : stop the Splash daemon gracefully
22
22
  # @param [Hash] content message content Hash Structure, ignored
@@ -46,6 +46,21 @@ module Splash
46
46
  return execute command: content[:payload][:name], ack: true
47
47
  end
48
48
 
49
+
50
+ # get_jobs verb : return list of scheduled jobs for internal scheduler
51
+ # @param [Hash] content message content Hash Structure, ignored
52
+ # @return [String] YAML dataset
53
+ def get_jobs(content)
54
+ return @server.jobs.to_yaml
55
+ end
56
+
57
+ # reset verb : reset the internal scheduler
58
+ # @param [Hash] content message content Hash Structure, ignored
59
+ # @return [String] "Scheduler reset" static
60
+ def reset(content)
61
+ return "Scheduler reset" if reset_orchestrator
62
+ end
63
+
49
64
  # execute_command verb : execute command specified in payload
50
65
  # @param [Hash] content message content Hash Structure, include mandatory payload[:name]
51
66
  # @return [Hash] Exiter case
@@ -17,8 +17,12 @@ module Splash
17
17
 
18
18
 
19
19
 
20
+
21
+
20
22
  # Rubygems
21
23
  begin
24
+ require 'net/ssh'
25
+ require 'net/scp'
22
26
  require 'prometheus/client'
23
27
  require 'prometheus/client/push'
24
28
  require 'thor'
@@ -35,6 +39,7 @@ module Splash
35
39
  require 'rest-client'
36
40
  require 'kramdown'
37
41
  require 'rack/reverse_proxy'
42
+ require 'tty-table'
38
43
 
39
44
 
40
45
  rescue Gem::GemNotFoundException
@@ -57,9 +62,9 @@ module Splash
57
62
 
58
63
  require 'splash/commands'
59
64
  require 'splash/sequences'
60
-
61
65
  require 'splash/logs'
62
66
  require 'splash/processes'
67
+ require 'splash/transfers'
63
68
 
64
69
  require 'splash/daemon'
65
70
  require 'splash/webadmin'
@@ -60,7 +60,7 @@ module Splash
60
60
 
61
61
  def splash_return(options = {})
62
62
 
63
- data = EXIT_MAP[options[:case]]
63
+ data = EXIT_MAP[options[:case]].clone
64
64
  data[:status] = (data[:code]>0)? :failure : :success
65
65
  data[:more] = options[:more] if options[:more]
66
66
  return data
@@ -252,7 +252,7 @@ module Splash
252
252
  # check folder
253
253
  # @return [Array] of Symbol with error type : [:inexistant,:mode,:owner,:group]
254
254
  # @param [Hash] options
255
- # @option options [String] :path folder path (relative or absolute)
255
+ # @option options [String] :name folder path (relative or absolute)
256
256
  # @option options [String] :mode String for OCTAL rights like "644", optionnal
257
257
  # @option options [String] :owner file owner for folder, optionnal
258
258
  # @option options [String] :group file group for folder, optionnal
@@ -336,12 +336,11 @@ module Splash
336
336
  end
337
337
  #!@endgroup
338
338
 
339
-
340
339
  def format_response(data, format)
341
340
  response = case format
342
341
  when 'application/json' then JSON.pretty_generate(data)
343
342
  when 'text/x-yaml' then data.to_yaml
344
- else JSON.pretty_generate(data)
343
+ else data.to_yaml
345
344
  end
346
345
  return response
347
346
  end
@@ -355,6 +354,16 @@ module Splash
355
354
  return result[extension]
356
355
  end
357
356
 
357
+ # check if unicode must be used with term ENV
358
+ # @return [Boolean]
359
+ def check_unicode_term
360
+ return false unless ENV.include? "TERM"
361
+ if ENV.values_at("LC_ALL","LC_CTYPE","LANG").compact.first.include?("UTF-8") and ENV.values_at('TERM').first.include? "xterm" then
362
+ return true
363
+ else
364
+ return false
365
+ end
366
+ end
358
367
 
359
368
  end
360
369
  end
@@ -10,6 +10,7 @@ module Splash
10
10
  class Cli < Splash::Loggers::LoggerTemplate
11
11
 
12
12
  include Splash::Config
13
+ include Splash::Helpers
13
14
 
14
15
  # mapping of UTf-8 emoji for log levels or alias
15
16
  EMOJI = { :unknown => "\u{1F4A5}",
@@ -82,16 +83,7 @@ module Splash
82
83
  get_config.loggers[:cli][:color] = status
83
84
  end
84
85
 
85
- # check if unicode must be used with term ENV
86
- # @return [Boolean]
87
- def check_unicode_term
88
- return false unless ENV.include? "TERM"
89
- if ENV.values_at("LC_ALL","LC_CTYPE","LANG").compact.first.include?("UTF-8") and ENV.values_at('TERM').first.include? "xterm" then
90
- return true
91
- else
92
- return false
93
- end
94
- end
86
+
95
87
 
96
88
  end
97
89
 
@@ -6,6 +6,83 @@ module Splash
6
6
  # Logs namespace
7
7
  module Logs
8
8
 
9
+ class LogsNotifier
10
+
11
+ @@registry = Prometheus::Client::Registry::new
12
+ @@metric_missing = Prometheus::Client::Gauge.new(:logmissing, docstring: 'SPLASH metric log missing', labels: [:log ])
13
+ @@metric_count = Prometheus::Client::Gauge.new(:logerrors, docstring: 'SPLASH metric log error', labels: [:log ])
14
+ @@metric_lines = Prometheus::Client::Gauge.new(:loglines, docstring: 'SPLASH metric log lines numbers', labels: [:log ])
15
+ @@registry.register(@@metric_count)
16
+ @@registry.register(@@metric_missing)
17
+ @@registry.register(@@metric_lines)
18
+
19
+ def initialize(options={})
20
+ @config = get_config
21
+ @url = @config.prometheus_pushgateway_url
22
+ @name = options[:name]
23
+ @missing = options[:missing]
24
+ @lines = options[:lines]
25
+ @errors = options[:errors]
26
+ end
27
+
28
+ # send metrics to Prometheus PushGateway
29
+ # @return [Bool]
30
+ def notify
31
+ unless verify_service url: @url then
32
+ return { :case => :service_dependence_missing, :more => "Prometheus Notification not send."}
33
+ end
34
+ @@metric_missing.set(@missing, labels: { log: @name })
35
+ @@metric_count.set(@errors, labels: { log: @name })
36
+ @@metric_lines.set(@lines, labels: { log: @name })
37
+ hostname = Socket.gethostname
38
+ return Prometheus::Client::Push.new("Splash", hostname, @url).add(@@registry)
39
+ end
40
+
41
+ end
42
+
43
+ class LogsRecords
44
+ include Splash::Backends
45
+ include Splash::Constants
46
+ def initialize(name)
47
+ @name = name
48
+ @backend = get_backend :logs_trace
49
+ end
50
+
51
+ def clear
52
+ @backend.del({:key => @name}) if @backend.exist?({key: @name})
53
+ end
54
+
55
+ def purge(retention)
56
+ retention = {} if retention.nil?
57
+ if retention.include? :hours then
58
+ adjusted_datetime = DateTime.now - retention[:hours].to_f / 24
59
+ elsif retention.include? :hours then
60
+ adjusted_datetime = DateTime.now - retention[:days].to_i
61
+ else
62
+ adjusted_datetime = DateTime.now - DEFAULT_RETENTION
63
+ end
64
+
65
+ data = get_all_records
66
+
67
+ data.delete_if { |item|
68
+ DateTime.parse(item.keys.first) <= (adjusted_datetime)}
69
+ @backend.put key: @name, value: data.to_yaml
70
+ end
71
+
72
+ def add_record(record)
73
+ data = get_all_records
74
+ data.push({ DateTime.now.to_s => record })
75
+ @backend.put key: @name, value: data.to_yaml
76
+ end
77
+
78
+ def get_all_records(options={})
79
+ return (@backend.exist?({key: @name}))? YAML::load(@backend.get({key: @name})) : []
80
+ end
81
+
82
+ end
83
+
84
+
85
+
9
86
  # Log scanner and notifier
10
87
  class LogScanner
11
88
  include Splash::Constants
@@ -17,13 +94,7 @@ module Splash
17
94
  def initialize
18
95
  @logs_target = Marshal.load(Marshal.dump(get_config.logs))
19
96
  @config = get_config
20
- @registry = Prometheus::Client::Registry::new
21
- @metric_count = Prometheus::Client::Gauge.new(:logerrors, docstring: 'SPLASH metric log error', labels: [:log ])
22
- @metric_missing = Prometheus::Client::Gauge.new(:logmissing, docstring: 'SPLASH metric log missing', labels: [:log ])
23
- @metric_lines = Prometheus::Client::Gauge.new(:loglines, docstring: 'SPLASH metric log lines numbers', labels: [:log ])
24
- @registry.register(@metric_count)
25
- @registry.register(@metric_missing)
26
- @registry.register(@metric_lines)
97
+
27
98
  end
28
99
 
29
100
 
@@ -62,17 +133,24 @@ module Splash
62
133
  session = (options[:session]) ? options[:session] : log.get_session
63
134
  log.info "Sending metrics to Prometheus Pushgateway", session
64
135
  @logs_target.each do |item|
65
- missing = (item[:status] == :missing)? 1 : 0
66
- log.item "Sending metrics for #{item[:log]}", session
67
- @metric_count.set(item[:count], labels: { log: item[:log] })
68
- @metric_missing.set(missing, labels: { log: item[:log] })
136
+ logsrec = LogsRecords::new item[:label]
137
+ errors = (item[:count])? item[:count] : 0
69
138
  lines = (item[:lines])? item[:lines] : 0
70
- @metric_lines.set(lines, labels: { log: item[:log] })
139
+ missing = (item[:status] == :missing)? 1 : 0
140
+ file = item[:log]
141
+ logsrec.purge(item[:retention])
142
+ logsrec.add_record :status => item[:status],
143
+ :errors => errors,
144
+ :lines => lines,
145
+ :file => file
146
+
147
+ logsmonitor = LogsNotifier::new({name: item[:label], missing: missing, file: file, errors: errors, lines: lines})
148
+ if logsmonitor.notify then
149
+ log.ok "Sending metrics for log #{file} to Prometheus Pushgateway", session
150
+ else
151
+ log.ko "Failed to send metrics for log #{file} to Prometheus Pushgateway", session
152
+ end
71
153
  end
72
- hostname = Socket.gethostname
73
- url = @config.prometheus_pushgateway_url
74
- Prometheus::Client::Push.new('Splash',hostname, url).add(@registry)
75
- log.ok "Sending to Prometheus PushGateway done.", session
76
154
  return {:case => :quiet_exit }
77
155
  end
78
156