prometheus-splash 0.5.3 → 0.6.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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +58 -60
  3. data/bin/splash +3 -0
  4. data/config/splash.yml +15 -2
  5. data/lib/splash/backends.rb +6 -0
  6. data/lib/splash/backends/file.rb +36 -0
  7. data/lib/splash/backends/redis.rb +44 -1
  8. data/lib/splash/cli.rb +7 -3
  9. data/lib/splash/cli/commands.rb +11 -4
  10. data/lib/splash/cli/config.rb +9 -1
  11. data/lib/splash/cli/daemon.rb +8 -1
  12. data/lib/splash/cli/documentation.rb +5 -2
  13. data/lib/splash/cli/logs.rb +14 -6
  14. data/lib/splash/cli/process.rb +9 -0
  15. data/lib/splash/cli/webadmin.rb +46 -0
  16. data/lib/splash/commands.rb +23 -2
  17. data/lib/splash/config.rb +141 -1
  18. data/lib/splash/config/flush.rb +9 -1
  19. data/lib/splash/config/sanitycheck.rb +6 -1
  20. data/lib/splash/config/service.rb +8 -1
  21. data/lib/splash/config/setup.rb +8 -3
  22. data/lib/splash/constants.rb +30 -2
  23. data/lib/splash/daemon.rb +5 -1
  24. data/lib/splash/daemon/controller.rb +21 -1
  25. data/lib/splash/daemon/metrics.rb +22 -7
  26. data/lib/splash/daemon/orchestrator.rb +21 -3
  27. data/lib/splash/daemon/orchestrator/grammar.rb +25 -5
  28. data/lib/splash/daemon/orchestrator/hooks.rb +10 -0
  29. data/lib/splash/dependencies.rb +10 -1
  30. data/lib/splash/exiter.rb +14 -0
  31. data/lib/splash/helpers.rb +69 -45
  32. data/lib/splash/loggers.rb +30 -4
  33. data/lib/splash/loggers/cli.rb +18 -3
  34. data/lib/splash/loggers/daemon.rb +14 -3
  35. data/lib/splash/loggers/dual.rb +14 -1
  36. data/lib/splash/loggers/web.rb +51 -0
  37. data/lib/splash/logs.rb +15 -4
  38. data/lib/splash/processes.rb +17 -5
  39. data/lib/splash/templates.rb +10 -0
  40. data/lib/splash/transports.rb +9 -0
  41. data/lib/splash/transports/rabbitmq.rb +33 -3
  42. data/lib/splash/webadmin.rb +122 -0
  43. data/lib/splash/webadmin/api/routes/commands.rb +28 -0
  44. data/lib/splash/webadmin/api/routes/config.rb +10 -0
  45. data/lib/splash/webadmin/api/routes/init.rb +2 -0
  46. data/lib/splash/webadmin/api/routes/logs.rb +59 -0
  47. data/lib/splash/webadmin/api/routes/process.rb +60 -0
  48. data/lib/splash/webadmin/main.rb +26 -0
  49. data/lib/splash/webadmin/portal/controllers/commands.rb +7 -0
  50. data/lib/splash/webadmin/portal/controllers/documentation.rb +6 -0
  51. data/lib/splash/webadmin/portal/controllers/home.rb +12 -0
  52. data/lib/splash/webadmin/portal/controllers/logs.rb +14 -0
  53. data/lib/splash/webadmin/portal/controllers/notfound.rb +5 -0
  54. data/lib/splash/webadmin/portal/controllers/processes.rb +14 -0
  55. data/lib/splash/webadmin/portal/controllers/proxy.rb +30 -0
  56. data/lib/splash/webadmin/portal/controllers/restclient.rb +19 -0
  57. data/lib/splash/webadmin/portal/init.rb +11 -0
  58. data/lib/splash/webadmin/portal/public/css/ultragreen.css +8544 -0
  59. data/lib/splash/webadmin/portal/public/fonts/FontAwesome.otf +0 -0
  60. data/lib/splash/webadmin/portal/public/fonts/fontawesome-webfont.ttf +0 -0
  61. data/lib/splash/webadmin/portal/public/fonts/fontawesome-webfont.woff +0 -0
  62. data/lib/splash/webadmin/portal/public/fonts/fontawesome-webfont.woff2 +0 -0
  63. data/lib/splash/webadmin/portal/public/images/logo_splash.png +0 -0
  64. data/lib/splash/webadmin/portal/public/images/logo_splash_reduce.png +0 -0
  65. data/lib/splash/webadmin/portal/public/images/logo_splash_tiny.png +0 -0
  66. data/lib/splash/webadmin/portal/views/commands.slim +49 -0
  67. data/lib/splash/webadmin/portal/views/documentation.slim +3 -0
  68. data/lib/splash/webadmin/portal/views/home.slim +78 -0
  69. data/lib/splash/webadmin/portal/views/layout.slim +43 -0
  70. data/lib/splash/webadmin/portal/views/logs.slim +32 -0
  71. data/lib/splash/webadmin/portal/views/nav.slim +17 -0
  72. data/lib/splash/webadmin/portal/views/not_found.slim +3 -0
  73. data/lib/splash/webadmin/portal/views/processes.slim +29 -0
  74. data/lib/splash/webadmin/portal/views/proxy.slim +13 -0
  75. data/lib/splash/webadmin/portal/views/restclient.slim +41 -0
  76. data/lib/splash/webadmin/portal/views/restclient_result.slim +29 -0
  77. data/prometheus-splash.gemspec +6 -0
  78. data/spec/helpers_spec.rb +119 -0
  79. metadata +128 -5
@@ -1,12 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ # base Splash module
1
4
  module Splash
5
+
6
+ # Splash Loggers module
2
7
  module Loggers
3
8
 
9
+ # Dual multiplexer specific logger
10
+ # log against CLi and Daemon
4
11
  class Dual #< Splash::Loggers::LoggerTemplate
5
12
 
6
13
 
7
14
  include Splash::Config
8
15
 
9
-
16
+ # build levels and alias forwarders
10
17
  LEVELS.each do |method|
11
18
  define_method(method) do |message,session = ''|
12
19
  self.log({ :level => method, :message => message, :session => session})
@@ -18,6 +25,7 @@ module Splash
18
25
  end
19
26
  end
20
27
 
28
+ # Constructor build two attributes for each loggers : Cli, Daemon
21
29
  def initialize
22
30
  super
23
31
  @log1 = Splash::Loggers::Cli::new
@@ -28,10 +36,15 @@ module Splash
28
36
  @log1.log options
29
37
  @log2.log options
30
38
  end
39
+
40
+ # getter for root level
41
+ # @return [Symbol] a level
31
42
  def level
32
43
  @level
33
44
  end
34
45
 
46
+ # setter for global level, both Cli and Daemon
47
+ # @param [Symbol] level a level in Splash::Loggers::LEVELS or Splash::Loggers::ALIAS
35
48
  def level=(level)
36
49
  @level = level
37
50
  @log1.level=level
@@ -0,0 +1,51 @@
1
+ # coding: utf-8
2
+
3
+ # base Splash module
4
+ module Splash
5
+
6
+ # Splash Loggers module
7
+ module Loggers
8
+
9
+ # Web specific logger
10
+ class Web < Splash::Loggers::LoggerTemplate
11
+
12
+
13
+ # contructor, open log file
14
+ # @return [Splash::Loggers::Web]
15
+ def initialize
16
+ self.level = get_config.loggers[:level]
17
+ @log_file = get_config.loggers[:web][:file]
18
+ @stream = File::open(@log_file, 'a')
19
+ @stream.sync = true
20
+ end
21
+
22
+ # log wrapper
23
+ # @param [Hash] options
24
+ # @option options [Symbol] :level defined in Splash::Loggers::LEVEL or Splash::Loggers::ALIAS
25
+ # @option options [String] :message
26
+ # @option options [String] :session a session number
27
+ # write formatted string to log file
28
+ def log(options)
29
+ pid = Process.pid.to_s
30
+ date = DateTime.now.to_s
31
+ level = (ALIAS.keys.include? options[:level])? ALIAS[options[:level]] : options[:level]
32
+ if @active_levels.include? level then
33
+ unless options[:session].empty? then
34
+ @stream.puts "[#{date}] (#{pid}) (#{options[:session]}) #{alt(options[:level])} : #{options[:message]}"
35
+ else
36
+ @stream.puts "[#{date}] (#{pid}) #{alt(options[:level])} : #{options[:message]}"
37
+ end
38
+ end
39
+ end
40
+
41
+ # close log file descriptor
42
+ def close
43
+ @stream.close
44
+ end
45
+
46
+
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -1,15 +1,21 @@
1
1
  # coding: utf-8
2
+
3
+ # base Splash module
2
4
  module Splash
5
+
6
+ # Logs namespace
3
7
  module Logs
8
+
9
+ # Log scanner and notifier
4
10
  class LogScanner
5
11
  include Splash::Constants
6
12
  include Splash::Config
7
13
 
8
14
 
9
- # LogScanner Constructor
10
- # return [LogScanner]
15
+ # LogScanner Constructor : initialize prometheus metrics
16
+ # return [Splash::Logs::LogScanner]
11
17
  def initialize
12
- @logs_target = get_config.logs
18
+ @logs_target = Marshal.load(Marshal.dump(get_config.logs))
13
19
  @config = get_config
14
20
  @registry = Prometheus::Client::Registry::new
15
21
  @metric_count = Prometheus::Client::Gauge.new(:logerrors, docstring: 'SPLASH metric log error', labels: [:log ])
@@ -22,6 +28,7 @@ module Splash
22
28
 
23
29
 
24
30
  # start log analyse for log target in config
31
+ # @return [Hash] Exiter case :quiet_exit
25
32
  def analyse
26
33
  @logs_target.each do |record|
27
34
  record[:count]=0 if record[:count].nil?
@@ -38,11 +45,15 @@ module Splash
38
45
  end
39
46
 
40
47
  # pseudo-accessor on @logs_target
48
+ # @return [Hash] the logs structure
41
49
  def output
42
50
  return @logs_target
43
51
  end
44
52
 
45
53
  # start notification on prometheus for metric logerrors, logmissing; loglines
54
+ # @param [Hash] options
55
+ # @option options [String] :session a session number for log daemon
56
+ # @return [Hash] Exiter case :quiet_exit
46
57
  def notify(options = {})
47
58
  log = get_logger
48
59
  unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
@@ -59,7 +70,7 @@ module Splash
59
70
  @metric_lines.set(lines, labels: { log: item[:log] })
60
71
  end
61
72
  hostname = Socket.gethostname
62
- url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
73
+ url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}/#{@config.prometheus_pushgateway_path}"
63
74
  Prometheus::Client::Push.new('Splash',hostname, url).add(@registry)
64
75
  log.ok "Sending to Prometheus PushGateway done.", session
65
76
  return {:case => :quiet_exit }
@@ -1,14 +1,21 @@
1
+ # coding: utf-8
2
+
3
+ # base Splash Module
1
4
  module Splash
5
+
6
+ # Processes namespace
2
7
  module Processes
8
+
9
+ # Processes scanner and notifier
3
10
  class ProcessScanner
4
11
  include Splash::Constants
5
12
  include Splash::Config
6
13
 
7
14
 
8
- # LogScanner Constructor
9
- # return [LogScanner]
15
+ # ProcessScanner Constructor : initialize prometheus metrics
16
+ # @return [Splash::Processes::ProcessScanner]
10
17
  def initialize
11
- @processes_target = get_config.processes
18
+ @processes_target = Marshal.load(Marshal.dump(get_config.processes))
12
19
  @config = get_config
13
20
  @registry = Prometheus::Client::Registry::new
14
21
  @metric_status = Prometheus::Client::Gauge.new(:process_status, docstring: 'SPLASH metric process status', labels: [:process ])
@@ -21,7 +28,8 @@ module Splash
21
28
  end
22
29
 
23
30
 
24
- # start log analyse for log target in config
31
+ # start process analyse for process target in config
32
+ # @return [Hash] Exiter case :quiet_exit
25
33
  def analyse
26
34
  @processes_target.each do |record|
27
35
  list = get_processes patterns: record[:patterns], full: true
@@ -39,11 +47,15 @@ module Splash
39
47
  end
40
48
 
41
49
  # pseudo-accessor on @processes_target
50
+ # @return [Hash] the processes structure
42
51
  def output
43
52
  return @processes_target
44
53
  end
45
54
 
46
55
  # start notification on prometheus for metrics
56
+ # @param [Hash] options
57
+ # @option options [String] :session a session number for log daemon
58
+ # @return [Hash] Exiter case :quiet_exit
47
59
  def notify(options = {})
48
60
  log = get_logger
49
61
  unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
@@ -60,7 +72,7 @@ module Splash
60
72
  @metric_mem_percent.set(item[:mem], labels: { process: item[:process] })
61
73
  end
62
74
  hostname = Socket.gethostname
63
- url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
75
+ url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}/#{@config.prometheus_pushgateway_path}"
64
76
  Prometheus::Client::Push.new('Splash',hostname, url).add(@registry)
65
77
  log.ok "Sending to Prometheus PushGateway done.", session
66
78
  return {:case => :quiet_exit }
@@ -1,12 +1,19 @@
1
1
  # coding: utf-8
2
+
3
+ # base Splash Module
2
4
  module Splash
5
+
6
+ # Templates namespace
3
7
  module Templates
4
8
 
5
9
  # KISS template Engine
6
10
  class Template
7
11
 
12
+ # getter of the list of token
8
13
  attr_reader :list_token
14
+ # getter of the template file
9
15
  attr_reader :template_file
16
+ # getter of the flat content of the template
10
17
  attr_reader :content
11
18
 
12
19
  # constructor : generate the pseudo accessor for template Class from token list
@@ -72,8 +79,11 @@ module Splash
72
79
 
73
80
  end
74
81
 
82
+ # Exception for an invalid Token list
75
83
  class InvalidTokenList < Exception; end
84
+ # Exception for an malformed token
76
85
  class NotAToken < Exception; end
86
+ # Exception for an invalid template file
77
87
  class NoTemplateFile < Exception; end
78
88
 
79
89
  end
@@ -1,9 +1,16 @@
1
1
  # coding: utf-8
2
2
 
3
+ # base Splash module
3
4
  module Splash
5
+
6
+ # Splash Transports namespace
4
7
  module Transports
5
8
  include Splash::Config
6
9
 
10
+
11
+ # factory for Splash::Transports::Rabbitmq::Subscriber
12
+ # @param [Hash] options
13
+ # @return [Splash::Transports::Rabbitmq::Subscriber|Hash] Subscriber or Exiter case :configuration_error
7
14
  def get_default_subscriber(options)
8
15
  config = get_config.transports
9
16
  transport = config[:active]
@@ -20,6 +27,8 @@ module Splash
20
27
  end
21
28
  end
22
29
 
30
+ # factory for Splash::Transports::Rabbitmq::Client
31
+ # @return [Splash::Transports::Rabbitmq::Client|Hash] Client or Exiter case :configuration_error
23
32
  def get_default_client
24
33
  config = get_config.transports
25
34
  transport = config[:active]
@@ -1,14 +1,24 @@
1
1
  # coding: utf-8
2
+
3
+ # base Splash module
2
4
  module Splash
5
+
6
+ # Splash Transports namespace
3
7
  module Transports
8
+
9
+ # RabbitMQ Transport
4
10
  module Rabbitmq
5
11
 
12
+ # Subscriber Mode RabbitMQ Client
6
13
  class Subscriber
7
14
  include Splash::Config
8
15
  extend Forwardable
9
16
 
10
17
  def_delegators :@queue, :subscribe
11
18
 
19
+ # Constructor Forward subscribe method and initialize a Bunny Client atribute @queue
20
+ # @param [Hash] options
21
+ # @option options [String] :queue the name of the subscribed queue
12
22
  def initialize(options = {})
13
23
  @config = get_config.transports
14
24
 
@@ -32,12 +42,13 @@ module Splash
32
42
 
33
43
  end
34
44
 
35
-
45
+ # publish / get Mode RabbitMQ Client
36
46
  class Client
37
47
  include Splash::Config
38
48
  include Splash::Transports
39
49
  include Splash::Loggers
40
50
 
51
+ # Constructor initialize a Bunny Client
41
52
  def initialize
42
53
  @config = get_config.transports
43
54
  host = @config[:rabbitmq][:host]
@@ -48,7 +59,7 @@ module Splash
48
59
  conf = { :host => host, :vhost => vhost, :user => user, :password => passwd, :port => port.to_i}
49
60
 
50
61
  begin
51
- @connection = Bunny.new conf
62
+ @connection = Bunny.new conf
52
63
  @connection.start
53
64
  @channel = @connection.create_channel
54
65
  rescue Bunny::Exception
@@ -56,19 +67,32 @@ module Splash
56
67
  end
57
68
  end
58
69
 
59
-
70
+ # purge a queue
71
+ # @param [Hash] options
72
+ # @option options [String] :queue the name of the queue to purge
60
73
  def purge(options)
61
74
  @channel.queue(options[:queue]).purge
62
75
  end
63
76
 
77
+ # publish to a queue
78
+ # @param [Hash] options
79
+ # @option options [String] :queue the name of the queue to purge
80
+ # @option options [String] :message the message to send
64
81
  def publish(options ={})
65
82
  return @channel.default_exchange.publish(options[:message], :routing_key => options[:queue])
66
83
  end
67
84
 
85
+ # ack a specific message for manual ack with a delivery tag to a queue
86
+ # @param [String] ack
87
+ # @return [Boolean]
68
88
  def ack(ack)
69
89
  return @channel.acknowledge(ack, false)
70
90
  end
71
91
 
92
+
93
+ # send an execution order message (verb+payload) via RabbitMQ to an slash input queue
94
+ # @param [Hash] order
95
+ # @return [Void] unserialized Void object from YAML
72
96
  def execute(order)
73
97
  queue = order[:return_to]
74
98
  lock = Mutex.new
@@ -85,6 +109,11 @@ module Splash
85
109
  return res
86
110
  end
87
111
 
112
+ # Get a message from a RabbitMQ queue
113
+ # @param [Hash] options
114
+ # @option options [String] :queue the name of the queue to query
115
+ # @option options [String] :manual_ack flag to inhibit ack
116
+ # @return [Hash] Payload + ack tag if :manual_ack
88
117
  def get(options ={})
89
118
  queue = @channel.queue(options[:queue])
90
119
  opt = {}; opt[:manual_ack] = (options[:manual_ack])? true : false
@@ -94,6 +123,7 @@ module Splash
94
123
  return res
95
124
  end
96
125
 
126
+ # close the RabbitMQ connection
97
127
  def close
98
128
  @connection.close
99
129
  end
@@ -0,0 +1,122 @@
1
+ # coding: utf-8
2
+
3
+
4
+
5
+ # base Splash module
6
+ module Splash
7
+
8
+ # global daemon module
9
+ module WebAdmin
10
+
11
+ # Daemon Controller Module
12
+ module Controller
13
+ include Splash::Constants
14
+ include Splash::Helpers
15
+ include Splash::Config
16
+ include Splash::Exiter
17
+ include Splash::Loggers
18
+
19
+
20
+ # Start the Splash Daemon
21
+ # @param [Hash] options
22
+ # @option options [Symbol] :quiet activate quiet mode for log (limit to :fatal)
23
+ # @return [Hash] Exiter Case (:quiet_exit, :already_exist, :unknown_error or other)
24
+ def startdaemon(options = {})
25
+ require 'splash/webadmin/main'
26
+ config = get_config
27
+ log = get_logger
28
+ log.level = :fatal if options[:quiet]
29
+ realpid = get_processes pattern: get_config.webadmin_process_name
30
+
31
+
32
+ unless File::exist? config.full_pid_path then
33
+ unless realpid.empty? then
34
+ return {:case => :already_exist, :more => "Splash WebAdmin Process already launched "}
35
+ end
36
+
37
+ daemon_config = {:description => config.webadmin_process_name,
38
+ :pid_file => config.webadmin_full_pid_path,
39
+ :stdout_trace => config.webadmin_full_stdout_trace_path,
40
+ :stderr_trace => config.webadmin_full_stderr_trace_path
41
+ }
42
+
43
+ ["int","term","hup"].each do |type| daemon_config["sig#{type}_handler".to_sym] = Proc::new { WebAdminApp.quit! } end
44
+ res = daemonize daemon_config do
45
+ log = get_logger logger: :web, force: true
46
+ log.info "Starting Splash WebAdmin"
47
+ WebAdminApp.run!
48
+ end
49
+ sleep 1
50
+ if res == 0 then
51
+ pid = `cat #{config.webadmin_full_pid_path}`.to_i
52
+ log.ok "Splash WebAdmin Started, with PID : #{pid}"
53
+ return {:case => :quiet_exit, :more => "Splash WebAdmin successfully loaded."}
54
+ else
55
+ return {:case => :unknown_error, :more => "Splash WebAdmin loading error, see logs for more details."}
56
+ end
57
+
58
+ else
59
+ return {:case => :already_exist, :more => "Pid File, please verify if Splash WebAdmin is running."}
60
+ end
61
+ end
62
+
63
+ # Stop the Splash WebAdmin
64
+ # @param [Hash] options
65
+ # @option options [Symbol] :quiet activate quiet mode for log (limit to :fatal)
66
+ # @return [Hash] Exiter Case (:quiet_exit, :not_found, other)
67
+ def stopdaemon(options = {})
68
+ config = get_config
69
+ log = get_logger
70
+ log.level = :fatal if options[:quiet]
71
+ if File.exist?(config.webadmin_full_pid_path) then
72
+ begin
73
+ pid = `cat #{config.webadmin_full_pid_path}`.to_i
74
+ Process.kill("TERM", pid)
75
+ acase = {:case => :quiet_exit, :more => 'Splash WebAdmin stopped succesfully'}
76
+ rescue Errno::ESRCH
77
+ acase = {:case => :not_found, :more => "Process of PID : #{pid} not found"}
78
+ end
79
+ FileUtils::rm config.webadmin_full_pid_path if File::exist? config.webadmin_full_pid_path
80
+ else
81
+ acase = {:case => :not_found, :more => "Splash WebAdmin is not running"}
82
+ end
83
+ return acase
84
+ end
85
+
86
+ # Status of the Splash WebAdmin, display status
87
+ # @param [Hash] options ignored
88
+ # @return [Hash] Exiter Case (:status_ko, :status_ok)
89
+ def statusdaemon(options = {})
90
+ log = get_logger
91
+ config = get_config
92
+ pid = realpid = ''
93
+ pid = `cat #{config.webadmin_full_pid_path}`.to_s if File.exist?(config.webadmin_full_pid_path)
94
+ listpid = get_processes({ :pattern => get_config.webadmin_process_name})
95
+ pid.chomp!
96
+ if listpid.empty? then
97
+ realpid = ''
98
+ else
99
+ realpid = listpid.first
100
+ end
101
+ unless realpid.empty? then
102
+ log.item "Splash WebAdmin Process is running with PID #{realpid} "
103
+ else
104
+ log.item 'Splash WebAdminProcess not found '
105
+ end
106
+ unless pid.empty? then
107
+ log.item "and PID file exist with PID #{pid}"
108
+ else
109
+ log.item "and PID file don't exist"
110
+ end
111
+ if pid == realpid then
112
+ return {:case => :status_ok }
113
+ elsif pid.empty? then
114
+ return {:case => :status_ko, :more => "PID File error, you have to kill process manualy, with : '(sudo )kill -TERM #{realpid}'"}
115
+ elsif realpid.empty? then
116
+ return {:case => :status_ko, :more => "Process Splash WebAdmin missing, run 'splash webadmin stop' before reload properly"}
117
+ end
118
+ end
119
+
120
+ end
121
+ end
122
+ end