prometheus-splash 0.3.0 → 0.4.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.
@@ -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