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.
@@ -6,25 +6,34 @@ module Splash
6
6
  include Splash::Helpers
7
7
  include Splash::Config
8
8
  include Splash::Orchestrator
9
+ include Splash::Exiter
10
+ include Splash::Loggers
9
11
 
10
12
  def startdaemon(options = {})
11
13
  config = get_config
14
+ log = get_logger
12
15
  unless verify_service host: config.prometheus_pushgateway_host ,port: config.prometheus_pushgateway_port then
13
16
  return {:case => :service_dependence_missing, :more => 'Prometheus Gateway'}
14
17
  end
15
18
  unless File::exist? config.full_pid_path then
16
- res = daemonize :description => config.daemon_process_name,
19
+ daemon_config = {:description => config.daemon_process_name,
17
20
  :pid_file => config.full_pid_path,
18
21
  :stdout_trace => config.full_stdout_trace_path,
19
- :stderr_trace => config.full_stderr_trace_path, :foreground => options[:foreground] do
22
+ :stderr_trace => config.full_stderr_trace_path,
23
+ :foreground => options[:foreground]
24
+ }
25
+
26
+ ["int","term","hup"].each do |type| daemon_config["sig#{type}_handler".to_sym] = Proc::new { ObjectSpace.each_object(Splash::Orchestrator::Scheduler).first.shutdown } end
27
+ res = daemonize daemon_config do
20
28
  Scheduler::new options
21
29
  end
30
+ sleep 1
22
31
  if res == 0 then
23
32
  pid = `cat #{config.full_pid_path}`.to_i
24
- puts "Splash Daemon Started, with PID : #{pid}"
25
- return {:case => :quiet_exit}
33
+ log.ok "Splash Daemon Started, with PID : #{pid}"
34
+ return {:case => :quiet_exit, :more => "Splash Daemon successfully loaded."}
26
35
  else
27
- return {:case => :unknown_error, :more => "Splash Daemon loading error, see logs for more details"}
36
+ return {:case => :unknown_error, :more => "Splash Daemon loading error, see logs for more details."}
28
37
  end
29
38
 
30
39
  else
@@ -49,7 +58,8 @@ module Splash
49
58
  return acase
50
59
  end
51
60
 
52
- def statusdaemon
61
+ def statusdaemon(options = {})
62
+ log = get_logger
53
63
  config = get_config
54
64
  pid = realpid = ''
55
65
  pid = `cat #{config.full_pid_path}`.to_s if File.exist?(config.full_pid_path)
@@ -57,14 +67,14 @@ module Splash
57
67
  pid.chomp!
58
68
  realpid.chomp!
59
69
  unless realpid.empty? then
60
- print "Splash Process is running with PID #{realpid} "
70
+ log.item "Splash Process is running with PID #{realpid} "
61
71
  else
62
- print 'Splash Process not found '
72
+ log.item 'Splash Process not found '
63
73
  end
64
74
  unless pid.empty? then
65
- puts "and PID file exist with PID #{pid}"
75
+ log.item "and PID file exist with PID #{pid}"
66
76
  else
67
- puts "and PID file don't exist"
77
+ log.item "and PID file don't exist"
68
78
  end
69
79
  if pid == realpid then
70
80
  return {:case => :status_ok }
@@ -24,6 +24,7 @@ module Splash
24
24
  require 'rufus-scheduler'
25
25
  require 'tty-markdown'
26
26
  require 'tty-pager'
27
+ require 'colorize'
27
28
  require "redis"
28
29
 
29
30
  rescue Gem::GemNotFoundException
@@ -37,11 +38,13 @@ module Splash
37
38
  require 'splash/constants'
38
39
  require 'splash/helpers'
39
40
  require 'splash/config'
41
+ require 'splash/loggers'
40
42
  require 'splash/exiter'
41
43
  require 'splash/templates'
42
44
  require 'splash/backends'
43
45
  require 'splash/transports'
44
46
 
47
+
45
48
  require 'splash/commands'
46
49
  require 'splash/logs'
47
50
  require 'splash/orchestrator'
data/lib/splash/exiter.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # coding: utf-8
2
2
  module Splash
3
3
  module Exiter
4
+ include Splash::Loggers
4
5
  EXIT_MAP= {
5
6
 
6
7
  # context execution
@@ -34,15 +35,16 @@ module Splash
34
35
  }
35
36
 
36
37
  def splash_exit(options = {})
38
+ log = get_logger
37
39
  mess = ""
38
40
  mess = EXIT_MAP[options[:case]][:message] if EXIT_MAP[options[:case]].include? :message
39
41
  mess << " : " unless mess.empty? or not options[:more]
40
42
  mess << "#{options[:more]}" if options[:more]
41
43
  if EXIT_MAP[options[:case]][:code] == 0 then
42
- puts mess unless mess.empty?
44
+ log.success mess unless mess.empty?
43
45
  exit 0
44
46
  else
45
- $stderr.puts mess unless mess.empty?
47
+ log.fatal mess unless mess.empty?
46
48
  exit EXIT_MAP[options[:case]][:code]
47
49
  end
48
50
  end
@@ -1,3 +1,4 @@
1
+ # @option options [String] :stdout_trace the path of the file where to redirect STDOUT
1
2
  # coding: utf-8
2
3
  module Splash
3
4
  module Helpers
@@ -89,6 +90,9 @@ module Splash
89
90
  # @option options [String] :daemon_group the group to change privileges
90
91
  # @option options [String] :stderr_trace the path of the file where to redirect STDERR
91
92
  # @option options [String] :stdout_trace the path of the file where to redirect STDOUT
93
+ # @option options [Proc] :sigint_handler handler Proc for SIGINT signal
94
+ # @option options [Proc] :sigterm_handler handler Proc for SIGTERM signal
95
+ # @option options [Proc] :sighup_handler handler Proc for SIGHuP signal
92
96
  # @option options [Bool] :foreground option to run foreground
93
97
  # @yield a process definion or block given
94
98
  # @example usage inline
@@ -129,11 +133,33 @@ module Splash
129
133
  #Process.euid = 0
130
134
  #Process.egid = 0
131
135
 
132
- trap("SIGINT"){ exit! 0 }
133
- trap("SIGTERM"){ exit! 0 }
134
- trap("SIGHUP"){ exit! 0 }
135
- return yield if options[:foreground]
136
+ trap("SIGINT"){
137
+ if options[:sigint_handler] then
138
+ options[:sigint_handler].call
139
+ else
140
+ exit! 0
141
+ end
142
+ }
143
+ trap("SIGTERM"){
144
+ if options[:sigterm_handler] then
145
+ options[:sigterm_handler].call
146
+ else
147
+ exit! 0
148
+ end
149
+ }
150
+ trap("SIGHUP"){
151
+ if options[:sighup_handler] then
152
+ options[:sighup_handler].call
153
+ else
154
+ exit! 0
155
+ end
156
+ }
157
+ if options[:foreground]
158
+ change_logger logger: :dual
159
+ return yield
160
+ end
136
161
  fork do
162
+ change_logger logger: :daemon
137
163
  #Process.daemon
138
164
  File.open(options[:pid_file],"w"){|f| f.puts Process.pid } if options[:pid_file]
139
165
  if options[:daemon_user] and options[:daemon_group] then
@@ -0,0 +1,89 @@
1
+ # coding: utf-8
2
+
3
+
4
+ module Splash
5
+ module Loggers
6
+ include Splash::Config
7
+
8
+ @@logger=nil
9
+
10
+ def get_logger(options = {})
11
+ logger = (get_config.loggers[:list].include? options[:logger])? options[:logger].to_s : get_config.loggers[:default].to_s
12
+ aclass = "Splash::Loggers::#{logger.capitalize}"
13
+ # begin
14
+ return @@logger = Kernel.const_get(aclass)::new if options[:force]
15
+ return @@logger ||= Kernel.const_get(aclass)::new
16
+ # rescue
17
+ # splash_exit case: :configuration_error, more: "Logger specified inexistant : #{logger}"
18
+ # end
19
+ end
20
+
21
+
22
+ def change_logger(options = {})
23
+ options[:force] = true
24
+ get_logger(options)
25
+ end
26
+
27
+
28
+
29
+ class LoggerTemplate
30
+ include Splash::Config
31
+
32
+ LEVELS = [:debug, :warn, :info, :result, :fatal, :unknown]
33
+ ALIAS = {:flat => :info, :item => :info, :ok => :info, :ko => :info, :trigger => :info,
34
+ :schedule => :info, :arrow => :info, :send => :info,
35
+ :receive => :info, :error => :result, :success => :result }
36
+ LEVELS.each do |method|
37
+ define_method(method) do |message|
38
+ self.log({ :level => method, :message => message})
39
+ end
40
+ end
41
+ ALIAS.keys.each do |method|
42
+ define_method(method) do |message|
43
+ self.log({ :level => method, :message => message})
44
+ end
45
+ end
46
+ def initialize
47
+ self.level = get_config.loggers[:level]
48
+
49
+
50
+ end
51
+
52
+
53
+ def log(options)
54
+ level = (ALIAS.keys.include? options[:level])? ALIAS[options[:level]] : options[:level]
55
+ if @active_levels.include? level then
56
+ puts options[:message]
57
+ end
58
+ end
59
+
60
+
61
+ def level
62
+ return @active_levels.first
63
+ end
64
+
65
+ def level=(level)
66
+ if LEVELS.include? level then
67
+ @active_levels = LEVELS.dup
68
+ @active_levels.shift(LEVELS.index(level))
69
+ else
70
+ raise BadLevel
71
+ end
72
+ end
73
+
74
+
75
+ private
76
+ def alt(symbol)
77
+ return "=>" if symbol == :arrow
78
+ return '' if symbol == :flat
79
+ return symbol.to_s.upcase
80
+ end
81
+
82
+ end
83
+
84
+ class BadLevel < Exception; end
85
+
86
+ end
87
+ end
88
+
89
+ Dir[File.dirname(__FILE__) + '/loggers/*.rb'].each {|file| require file }
@@ -0,0 +1,83 @@
1
+ # coding: utf-8
2
+ module Splash
3
+ module Loggers
4
+
5
+ class Cli < Splash::Loggers::LoggerTemplate
6
+
7
+ include Splash::Config
8
+
9
+ EMOJI = { :unknown => "\u{1F4A5}",
10
+ :fatal => "\u{26D4}",
11
+ :error => "\u{1F6AB}",
12
+ :ko => "\u{1F44E}",
13
+ :warn => "\u{26A0}",
14
+ :info => "\u{2139}",
15
+ :item => " \u{1F539}",
16
+ :arrow => " \u{27A1}",
17
+ :schedule => "\u{23F1}",
18
+ :trigger => "\u{23F0}",
19
+ :send => "\u{1F4E4}",
20
+ :receive => "\u{1F4E5}",
21
+ :ok => "\u{1F44D}",
22
+ :success => "\u{1F4AA}",
23
+ :debug => "\u{1F41B}"}
24
+
25
+ COLORS = { :unknown => :red,
26
+ :fatal => :red,
27
+ :error => :red,
28
+ :ko => :yellow,
29
+ :warn => :yellow,
30
+ :item => :white,
31
+ :arrow => :white,
32
+ :send => :white,
33
+ :schedule => :white,
34
+ :trigger => :white,
35
+ :receive => :white,
36
+ :info => :cyan,
37
+ :ok => :green,
38
+ :success => :green,
39
+ :debug => :magenta}
40
+
41
+
42
+
43
+ def log(options)
44
+ level = (ALIAS.keys.include? options[:level])? ALIAS[options[:level]] : options[:level]
45
+ if @active_levels.include? level then
46
+ if options[:level] == :flat then
47
+ puts options[:message]
48
+ else
49
+ String.disable_colorization = !get_config.loggers[:cli][:color]
50
+ emoji = get_config.loggers[:cli][:emoji]
51
+ emoji = check_unicode_term if emoji
52
+ if emoji then
53
+ display = "#{EMOJI[options[:level]]} #{options[:message]}"
54
+ else
55
+ display = "#{alt(options[:level])} #{options[:message]}"
56
+ end
57
+ puts display.colorize(COLORS[options[:level]])
58
+ end
59
+ end
60
+ end
61
+
62
+ def emoji=(status)
63
+ get_config.loggers[:cli][:emoji] = status
64
+ end
65
+
66
+ def color=(status)
67
+ get_config.loggers[:cli][:color] = status
68
+ end
69
+
70
+ def check_unicode_term
71
+ if ENV.values_at("LC_ALL","LC_CTYPE","LANG").compact.first.include?("UTF-8") and ENV.values_at('TERM').first.include? "xterm" then
72
+ return true
73
+ else
74
+ return false
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ class BadLevel < Exception; end
81
+
82
+ end
83
+ end
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ module Splash
3
+ module Loggers
4
+
5
+
6
+ class Daemon < Splash::Loggers::LoggerTemplate
7
+
8
+
9
+
10
+ def initialize
11
+ self.level = get_config.loggers[:level]
12
+ @log_file = get_config.loggers[:daemon][:file]
13
+ @stream = File::open(@log_file, 'a')
14
+ @stream.sync = true
15
+ end
16
+
17
+
18
+ def log(options)
19
+ level = (ALIAS.keys.include? options[:level])? ALIAS[options[:level]] : options[:level]
20
+ if @active_levels.include? level then
21
+ @stream.puts "#{alt(options[:level])} #{options[:message]}"
22
+ end
23
+ end
24
+
25
+ def close
26
+ @stream.close
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ module Splash
2
+ module Loggers
3
+
4
+ class Dual < Splash::Loggers::LoggerTemplate
5
+ include Splash::Config
6
+
7
+
8
+
9
+ def initialize
10
+ super
11
+ @log1 = Splash::Loggers::Cli::new
12
+ @log2 = Splash::Loggers::Daemon::new
13
+ end
14
+
15
+ def log(options)
16
+ @log1.log options
17
+ @log2.log options
18
+ end
19
+
20
+ end
21
+ end
22
+ end
data/lib/splash/logs.rb CHANGED
@@ -43,13 +43,14 @@ module Splash
43
43
 
44
44
  # start notification on prometheus for metric logerrors, logmissing; loglines
45
45
  def notify
46
+ log = get_logger
46
47
  unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
47
48
  return { :case => :service_dependence_missing, :more => "Prometheus Notification not send." }
48
49
  end
49
- puts "Sending metrics to Prometheus Pushgateway"
50
+ log.info "Sending metrics to Prometheus Pushgateway"
50
51
  @logs_target.each do |item|
51
52
  missing = (item[:status] == :missing)? 1 : 0
52
- puts " * Sending metrics for #{item[:log]}"
53
+ log.item "Sending metrics for #{item[:log]}"
53
54
  @metric_count.set(item[:count], labels: { log: item[:log] })
54
55
  @metric_missing.set(missing, labels: { log: item[:log] })
55
56
  lines = (item[:lines])? item[:lines] : 0
@@ -58,7 +59,7 @@ module Splash
58
59
  hostname = Socket.gethostname
59
60
  url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
60
61
  Prometheus::Client::Push.new('Splash',hostname, url).add(@registry)
61
- puts "Sending done."
62
+ log.ok "Sending to Prometheus PushGateway done."
62
63
  return {:case => :quiet_exit }
63
64
  end
64
65
 
@@ -12,27 +12,30 @@ module Splash
12
12
  include Splash::Config
13
13
  include Splash::Transports
14
14
  include Splash::Orchestrator::Grammar
15
+ include Splash::Loggers
16
+
15
17
  def initialize(options = {})
18
+ @log = get_logger
16
19
  $stdout.sync = true
17
20
  $stderr.sync = true
18
21
  @server = Rufus::Scheduler::new
19
22
  @server.extend SchedulerHooks
20
23
  @config = get_config
21
24
  @result = LogScanner::new
22
- puts "Splash Orchestrator starting :"
25
+ @log.info "Splash Orchestrator starting :"
23
26
  if options[:scheduling] then
24
- puts " * Initializing commands Scheduling."
27
+ @log.item "Initializing commands Scheduling."
25
28
  self.init_commands_scheduling
26
29
  end
27
30
  sched,value = @config.daemon_logmon_scheduling.flatten
28
- puts " * Initializing logs monitorings & notifications."
31
+ @log.item "Initializing logs monitorings & notifications."
29
32
  @server.send sched,value do
30
33
  begin
34
+ @log.trigger "Logs monitoring for Scheduling : #{sched.to_s} #{value.to_s}"
31
35
  @result.analyse
32
36
  @result.notify
33
- $stdout.flush
34
37
  rescue Errno::ECONNREFUSED
35
- $stderr.puts "PushGateway seems to be done, please start it."
38
+ @log.error "PushGateway seems to be done, please start it."
36
39
  end
37
40
  end
38
41
  hostname = Socket.gethostname
@@ -43,21 +46,26 @@ module Splash
43
46
  transport.subscribe(:block => true) do |delivery_info, properties, body|
44
47
  content = YAML::load(body)
45
48
  if VERBS.include? content[:verb]
46
- puts "Receive valid remote order, verb : #{content[:verb].to_s}"
49
+ @log.receive "Valid remote order, verb : #{content[:verb].to_s}"
47
50
  if content[:payload] then
48
51
  res = self.send content[:verb], content[:payload]
49
52
  else
50
53
  res = self.send content[:verb]
51
54
  end
52
55
  get_default_client.publish queue: content[:return_to], message: res.to_yaml
56
+ @log.send "Result to #{content[:return_to]}."
53
57
  else
54
- puts "Receive INVALID remote order, verb : #{content[:verb].to_s}"
58
+ @log.receive "INVALID remote order, verb : #{content[:verb].to_s}"
55
59
  get_default_client.publish queue: content[:return_to], message: "Unkown verb #{content[:verb]}".to_yaml
56
60
  end
57
61
  end
58
62
  end
59
63
 
60
64
  def terminate
65
+ @log.info "Splash daemon shutdown"
66
+ @server.shutdown
67
+ change_logger logger: :cli
68
+ splash_exit case: :quiet_exit
61
69
  end
62
70
 
63
71
  private
@@ -66,8 +74,9 @@ module Splash
66
74
  commands = config.select{|key,value| value.include? :schedule}.keys
67
75
  commands.each do |command|
68
76
  sched,value = config[command][:schedule].flatten
69
- puts " => Scheduling command #{command.to_s}"
77
+ @log.arrow "Scheduling command #{command.to_s}"
70
78
  @server.send sched,value do
79
+ @log.trigger "Executing Scheduled command #{command.to_s} for Scheduling : #{sched.to_s} #{value.to_s}"
71
80
  self.execute command: command.to_s
72
81
  end
73
82
  end