prometheus-splash 0.5.3 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -1
  3. data/README.md +58 -60
  4. data/bin/splash +3 -0
  5. data/config/splash.yml +110 -11
  6. data/lib/splash/backends.rb +7 -0
  7. data/lib/splash/backends/file.rb +36 -0
  8. data/lib/splash/backends/redis.rb +44 -1
  9. data/lib/splash/cli.rb +11 -4
  10. data/lib/splash/cli/commands.rb +136 -9
  11. data/lib/splash/cli/config.rb +9 -1
  12. data/lib/splash/cli/daemon.rb +49 -2
  13. data/lib/splash/cli/documentation.rb +5 -2
  14. data/lib/splash/cli/logs.rb +116 -47
  15. data/lib/splash/cli/process.rb +121 -52
  16. data/lib/splash/cli/sequences.rb +114 -0
  17. data/lib/splash/cli/transfers.rb +213 -0
  18. data/lib/splash/cli/webadmin.rb +46 -0
  19. data/lib/splash/commands.rb +111 -23
  20. data/lib/splash/config.rb +174 -23
  21. data/lib/splash/config/flush.rb +9 -1
  22. data/lib/splash/config/sanitycheck.rb +7 -2
  23. data/lib/splash/config/service.rb +8 -1
  24. data/lib/splash/config/setup.rb +8 -3
  25. data/lib/splash/constants.rb +37 -8
  26. data/lib/splash/daemon.rb +5 -1
  27. data/lib/splash/daemon/controller.rb +31 -11
  28. data/lib/splash/daemon/metrics.rb +29 -14
  29. data/lib/splash/daemon/orchestrator.rb +114 -35
  30. data/lib/splash/daemon/orchestrator/grammar.rb +40 -5
  31. data/lib/splash/daemon/orchestrator/hooks.rb +10 -0
  32. data/lib/splash/dependencies.rb +18 -1
  33. data/lib/splash/exiter.rb +14 -0
  34. data/lib/splash/helpers.rb +88 -46
  35. data/lib/splash/loggers.rb +30 -4
  36. data/lib/splash/loggers/cli.rb +18 -11
  37. data/lib/splash/loggers/daemon.rb +14 -3
  38. data/lib/splash/loggers/dual.rb +14 -1
  39. data/lib/splash/loggers/web.rb +51 -0
  40. data/lib/splash/logs.rb +105 -20
  41. data/lib/splash/processes.rb +104 -21
  42. data/lib/splash/sequences.rb +105 -0
  43. data/lib/splash/templates.rb +10 -0
  44. data/lib/splash/transfers.rb +229 -0
  45. data/lib/splash/transports.rb +9 -0
  46. data/lib/splash/transports/rabbitmq.rb +33 -4
  47. data/lib/splash/webadmin.rb +122 -0
  48. data/lib/splash/webadmin/api/routes/commands.rb +28 -0
  49. data/lib/splash/webadmin/api/routes/config.rb +10 -0
  50. data/lib/splash/webadmin/api/routes/init.rb +2 -0
  51. data/lib/splash/webadmin/api/routes/logs.rb +59 -0
  52. data/lib/splash/webadmin/api/routes/process.rb +60 -0
  53. data/lib/splash/webadmin/api/routes/sequences.rb +28 -0
  54. data/lib/splash/webadmin/main.rb +27 -0
  55. data/lib/splash/webadmin/portal/controllers/commands.rb +7 -0
  56. data/lib/splash/webadmin/portal/controllers/documentation.rb +6 -0
  57. data/lib/splash/webadmin/portal/controllers/home.rb +31 -0
  58. data/lib/splash/webadmin/portal/controllers/logs.rb +14 -0
  59. data/lib/splash/webadmin/portal/controllers/notfound.rb +5 -0
  60. data/lib/splash/webadmin/portal/controllers/processes.rb +14 -0
  61. data/lib/splash/webadmin/portal/controllers/proxy.rb +36 -0
  62. data/lib/splash/webadmin/portal/controllers/restclient.rb +19 -0
  63. data/lib/splash/webadmin/portal/controllers/sequences.rb +7 -0
  64. data/lib/splash/webadmin/portal/init.rb +11 -0
  65. data/lib/splash/webadmin/portal/public/css/ultragreen.css +8544 -0
  66. data/lib/splash/webadmin/portal/public/fonts/FontAwesome.otf +0 -0
  67. data/lib/splash/webadmin/portal/public/fonts/fontawesome-webfont.ttf +0 -0
  68. data/lib/splash/webadmin/portal/public/fonts/fontawesome-webfont.woff +0 -0
  69. data/lib/splash/webadmin/portal/public/fonts/fontawesome-webfont.woff2 +0 -0
  70. data/lib/splash/webadmin/portal/public/images/logo_splash.png +0 -0
  71. data/lib/splash/webadmin/portal/public/images/logo_splash_reduce.png +0 -0
  72. data/lib/splash/webadmin/portal/public/images/logo_splash_tiny.png +0 -0
  73. data/lib/splash/webadmin/portal/views/commands.slim +49 -0
  74. data/lib/splash/webadmin/portal/views/documentation.slim +3 -0
  75. data/lib/splash/webadmin/portal/views/home.slim +123 -0
  76. data/lib/splash/webadmin/portal/views/layout.slim +43 -0
  77. data/lib/splash/webadmin/portal/views/logs.slim +32 -0
  78. data/lib/splash/webadmin/portal/views/nav.slim +17 -0
  79. data/lib/splash/webadmin/portal/views/not_found.slim +3 -0
  80. data/lib/splash/webadmin/portal/views/processes.slim +29 -0
  81. data/lib/splash/webadmin/portal/views/proxy.slim +16 -0
  82. data/lib/splash/webadmin/portal/views/restclient.slim +41 -0
  83. data/lib/splash/webadmin/portal/views/restclient_result.slim +29 -0
  84. data/lib/splash/webadmin/portal/views/sequences.slim +50 -0
  85. data/prometheus-splash.gemspec +11 -2
  86. data/spec/helpers_spec.rb +119 -0
  87. metadata +191 -5
@@ -1,12 +1,17 @@
1
1
  # coding: utf-8
2
+
3
+ # base Splash module
2
4
  module Splash
3
- module Loggers
4
5
 
6
+ # Splash Loggers module
7
+ module Loggers
5
8
 
9
+ # Daemon specific logger
6
10
  class Daemon < Splash::Loggers::LoggerTemplate
7
11
 
8
12
 
9
-
13
+ # contructor, open log file
14
+ # @return [Splash::Loggers::Daemon]
10
15
  def initialize
11
16
  self.level = get_config.loggers[:level]
12
17
  @log_file = get_config.loggers[:daemon][:file]
@@ -14,7 +19,12 @@ module Splash
14
19
  @stream.sync = true
15
20
  end
16
21
 
17
-
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
18
28
  def log(options)
19
29
  pid = Process.pid.to_s
20
30
  date = DateTime.now.to_s
@@ -28,6 +38,7 @@ module Splash
28
38
  end
29
39
  end
30
40
 
41
+ # close log file descriptor
31
42
  def close
32
43
  @stream.close
33
44
  end
@@ -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,27 +1,101 @@
1
1
  # coding: utf-8
2
+
3
+ # base Splash module
2
4
  module Splash
5
+
6
+ # Logs namespace
3
7
  module Logs
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 purge(retention)
52
+ retention = {} if retention.nil?
53
+ if retention.include? :hours then
54
+ adjusted_datetime = DateTime.now - retention[:hours].to_f / 24
55
+ elsif retention.include? :hours then
56
+ adjusted_datetime = DateTime.now - retention[:days].to_i
57
+ else
58
+ adjusted_datetime = DateTime.now - DEFAULT_RETENTION
59
+ end
60
+
61
+ data = get_all_records
62
+
63
+ data.delete_if { |item|
64
+ DateTime.parse(item.keys.first) <= (adjusted_datetime)}
65
+ @backend.put key: @name, value: data.to_yaml
66
+ end
67
+
68
+ def add_record(record)
69
+ data = get_all_records
70
+ data.push({ DateTime.now.to_s => record })
71
+ @backend.put key: @name, value: data.to_yaml
72
+ end
73
+
74
+ def get_all_records(options={})
75
+ return (@backend.exist?({key: @name}))? YAML::load(@backend.get({key: @name})) : []
76
+ end
77
+
78
+ end
79
+
80
+
81
+
82
+ # Log scanner and notifier
4
83
  class LogScanner
5
84
  include Splash::Constants
6
85
  include Splash::Config
7
86
 
8
87
 
9
- # LogScanner Constructor
10
- # return [LogScanner]
88
+ # LogScanner Constructor : initialize prometheus metrics
89
+ # return [Splash::Logs::LogScanner]
11
90
  def initialize
12
- @logs_target = get_config.logs
91
+ @logs_target = Marshal.load(Marshal.dump(get_config.logs))
13
92
  @config = get_config
14
- @registry = Prometheus::Client::Registry::new
15
- @metric_count = Prometheus::Client::Gauge.new(:logerrors, docstring: 'SPLASH metric log error', labels: [:log ])
16
- @metric_missing = Prometheus::Client::Gauge.new(:logmissing, docstring: 'SPLASH metric log missing', labels: [:log ])
17
- @metric_lines = Prometheus::Client::Gauge.new(:loglines, docstring: 'SPLASH metric log lines numbers', labels: [:log ])
18
- @registry.register(@metric_count)
19
- @registry.register(@metric_missing)
20
- @registry.register(@metric_lines)
93
+
21
94
  end
22
95
 
23
96
 
24
97
  # start log analyse for log target in config
98
+ # @return [Hash] Exiter case :quiet_exit
25
99
  def analyse
26
100
  @logs_target.each do |record|
27
101
  record[:count]=0 if record[:count].nil?
@@ -38,30 +112,41 @@ module Splash
38
112
  end
39
113
 
40
114
  # pseudo-accessor on @logs_target
115
+ # @return [Hash] the logs structure
41
116
  def output
42
117
  return @logs_target
43
118
  end
44
119
 
45
120
  # start notification on prometheus for metric logerrors, logmissing; loglines
121
+ # @param [Hash] options
122
+ # @option options [String] :session a session number for log daemon
123
+ # @return [Hash] Exiter case :quiet_exit
46
124
  def notify(options = {})
47
125
  log = get_logger
48
- unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
126
+ unless verify_service url: @config.prometheus_pushgateway_url then
49
127
  return { :case => :service_dependence_missing, :more => "Prometheus Notification not send." }
50
128
  end
51
129
  session = (options[:session]) ? options[:session] : log.get_session
52
130
  log.info "Sending metrics to Prometheus Pushgateway", session
53
131
  @logs_target.each do |item|
54
- missing = (item[:status] == :missing)? 1 : 0
55
- log.item "Sending metrics for #{item[:log]}", session
56
- @metric_count.set(item[:count], labels: { log: item[:log] })
57
- @metric_missing.set(missing, labels: { log: item[:log] })
132
+ logsrec = LogsRecords::new item[:label]
133
+ errors = (item[:count])? item[:count] : 0
58
134
  lines = (item[:lines])? item[:lines] : 0
59
- @metric_lines.set(lines, labels: { log: item[:log] })
135
+ missing = (item[:status] = :missing)? 1 : 0
136
+ file = item[:log]
137
+ logsrec.purge(item[:retention])
138
+ logsrec.add_record :status => item[:status],
139
+ :errors => errors,
140
+ :lines => lines,
141
+ :file => file
142
+
143
+ logsmonitor = LogsNotifier::new({name: item[:label], missing: missing, file: file, errors: errors, lines: lines})
144
+ if logsmonitor.notify then
145
+ log.ok "Sending metrics for log #{file} to Prometheus Pushgateway", session
146
+ else
147
+ log.ko "Failed to send metrics for log #{file} to Prometheus Pushgateway", session
148
+ end
60
149
  end
61
- hostname = Socket.gethostname
62
- url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
63
- Prometheus::Client::Push.new('Splash',hostname, url).add(@registry)
64
- log.ok "Sending to Prometheus PushGateway done.", session
65
150
  return {:case => :quiet_exit }
66
151
  end
67
152
 
@@ -1,27 +1,102 @@
1
+ # coding: utf-8
2
+
3
+ # base Splash Module
1
4
  module Splash
5
+
6
+ # Processes namespace
2
7
  module Processes
8
+
9
+
10
+ class ProcessNotifier
11
+
12
+ @@registry = Prometheus::Client::Registry::new
13
+ @@metric_status = Prometheus::Client::Gauge.new(:process_status, docstring: 'SPLASH metric process status', labels: [:process ])
14
+ @@metric_cpu_percent = Prometheus::Client::Gauge.new(:process_cpu_percent, docstring: 'SPLASH metric process CPU usage in percent', labels: [:process ])
15
+ @@metric_mem_percent = Prometheus::Client::Gauge.new(:process_mem_percent, docstring: 'SPLASH metric process MEM usage in percent', labels: [:process ])
16
+ @@registry.register(@@metric_status)
17
+ @@registry.register(@@metric_cpu_percent)
18
+ @@registry.register(@@metric_mem_percent)
19
+
20
+
21
+ def initialize(options={})
22
+ @config = get_config
23
+ @url = @config.prometheus_pushgateway_url
24
+ @name = options[:name]
25
+ @status = options[:status]
26
+ @cpu_percent = options[:cpu_percent]
27
+ @mem_percent = options[:mem_percent]
28
+ end
29
+
30
+ # send metrics to Prometheus PushGateway
31
+ # @return [Bool]
32
+ def notify
33
+ unless verify_service url: @url then
34
+ return { :case => :service_dependence_missing, :more => "Prometheus Notification not send."}
35
+ end
36
+ @@metric_mem_percent.set(@mem_percent, labels: { process: @name })
37
+ @@metric_cpu_percent.set(@cpu_percent, labels: { process: @name })
38
+ @@metric_status.set(@status, labels: { process: @name })
39
+ hostname = Socket.gethostname
40
+ return Prometheus::Client::Push.new("Splash", hostname, @url).add(@@registry)
41
+ end
42
+
43
+ end
44
+
45
+
46
+ class ProcessRecords
47
+ include Splash::Backends
48
+ include Splash::Constants
49
+
50
+ def initialize(name)
51
+ @name = name
52
+ @backend = get_backend :process_trace
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
+ # Processes scanner and notifier
3
85
  class ProcessScanner
4
86
  include Splash::Constants
5
87
  include Splash::Config
6
88
 
7
89
 
8
- # LogScanner Constructor
9
- # return [LogScanner]
90
+ # ProcessScanner Constructor : initialize prometheus metrics
91
+ # @return [Splash::Processes::ProcessScanner]
10
92
  def initialize
11
- @processes_target = get_config.processes
93
+ @processes_target = Marshal.load(Marshal.dump(get_config.processes))
12
94
  @config = get_config
13
- @registry = Prometheus::Client::Registry::new
14
- @metric_status = Prometheus::Client::Gauge.new(:process_status, docstring: 'SPLASH metric process status', labels: [:process ])
15
- @metric_cpu_percent = Prometheus::Client::Gauge.new(:process_cpu_percent, docstring: 'SPLASH metric process CPU usage in percent', labels: [:process ])
16
- @metric_mem_percent = Prometheus::Client::Gauge.new(:process_mem_percent, docstring: 'SPLASH metric process MEM usage in percent', labels: [:process ])
17
- @registry.register(@metric_status)
18
- @registry.register(@metric_cpu_percent)
19
- @registry.register(@metric_mem_percent)
20
-
21
95
  end
22
96
 
23
97
 
24
- # start log analyse for log target in config
98
+ # start process analyse for process target in config
99
+ # @return [Hash] Exiter case :quiet_exit
25
100
  def analyse
26
101
  @processes_target.each do |record|
27
102
  list = get_processes patterns: record[:patterns], full: true
@@ -39,30 +114,38 @@ module Splash
39
114
  end
40
115
 
41
116
  # pseudo-accessor on @processes_target
117
+ # @return [Hash] the processes structure
42
118
  def output
43
119
  return @processes_target
44
120
  end
45
121
 
46
122
  # start notification on prometheus for metrics
123
+ # @param [Hash] options
124
+ # @option options [String] :session a session number for log daemon
125
+ # @return [Hash] Exiter case :quiet_exit
47
126
  def notify(options = {})
48
127
  log = get_logger
49
- unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
128
+ unless verify_service url: @config.prometheus_pushgateway_url then
50
129
  return { :case => :service_dependence_missing, :more => "Prometheus Notification not send." }
51
130
  end
52
131
  session = (options[:session]) ? options[:session] : log.get_session
53
132
  log.info "Sending metrics to Prometheus Pushgateway", session
54
133
  @processes_target.each do |item|
134
+ processrec = ProcessRecords::new item[:process]
55
135
  missing = (item[:status] == :missing)? 1 : 0
56
- log.item "Sending metrics for #{item[:process]}", session
57
136
  val = (item[:status] == :running )? 1 : 0
58
- @metric_status.set(val, labels: { process: item[:process] })
59
- @metric_cpu_percent.set(item[:cpu], labels: { process: item[:process] })
60
- @metric_mem_percent.set(item[:mem], labels: { process: item[:process] })
137
+ processrec.purge(item[:retention])
138
+ processrec.add_record :status => item[:status],
139
+ :cpu_percent => item[:cpu],
140
+ :mem_percent => item[:mem] ,
141
+ :process => item[:process]
142
+ processmonitor = ProcessNotifier::new({name: item[:process], status: val , cpu_percent: item[:cpu], mem_percent: item[:mem]})
143
+ if processmonitor.notify then
144
+ log.ok "Sending metrics for process #{item[:process]} to Prometheus Pushgateway", session
145
+ else
146
+ log.ko "Failed to send metrics for process #{item[:process]} to Prometheus Pushgateway", session
147
+ end
61
148
  end
62
- hostname = Socket.gethostname
63
- url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
64
- Prometheus::Client::Push.new('Splash',hostname, url).add(@registry)
65
- log.ok "Sending to Prometheus PushGateway done.", session
66
149
  return {:case => :quiet_exit }
67
150
  end
68
151