parent
08946efdc8
commit
e5a854e740
@ -1,205 +1,69 @@ |
||||
# The following was taken from github.com/crohr/syslogger and is BSD |
||||
# licensed. |
||||
require 'syslog' |
||||
require 'logger' |
||||
require 'thread' |
||||
worker_processes 3 |
||||
|
||||
class Syslogger |
||||
|
||||
VERSION = "1.6.0" |
||||
|
||||
attr_reader :level, :ident, :options, :facility, :max_octets |
||||
attr_accessor :formatter |
||||
|
||||
MAPPING = { |
||||
Logger::DEBUG => Syslog::LOG_DEBUG, |
||||
Logger::INFO => Syslog::LOG_INFO, |
||||
Logger::WARN => Syslog::LOG_WARNING, |
||||
Logger::ERROR => Syslog::LOG_ERR, |
||||
Logger::FATAL => Syslog::LOG_CRIT, |
||||
Logger::UNKNOWN => Syslog::LOG_ALERT |
||||
} |
||||
|
||||
# |
||||
# Initializes default options for the logger |
||||
# <tt>ident</tt>:: the name of your program [default=$0]. |
||||
# <tt>options</tt>:: syslog options [default=<tt>Syslog::LOG_PID | Syslog::LOG_CONS</tt>]. |
||||
# Correct values are: |
||||
# LOG_CONS : writes the message on the console if an error occurs when sending the message; |
||||
# LOG_NDELAY : no delay before sending the message; |
||||
# LOG_PERROR : messages will also be written on STDERR; |
||||
# LOG_PID : adds the process number to the message (just after the program name) |
||||
# <tt>facility</tt>:: the syslog facility [default=nil] Correct values include: |
||||
# Syslog::LOG_DAEMON |
||||
# Syslog::LOG_USER |
||||
# Syslog::LOG_SYSLOG |
||||
# Syslog::LOG_LOCAL2 |
||||
# Syslog::LOG_NEWS |
||||
# etc. |
||||
# |
||||
# Usage: |
||||
# logger = Syslogger.new("my_app", Syslog::LOG_PID | Syslog::LOG_CONS, Syslog::LOG_LOCAL0) |
||||
# logger.level = Logger::INFO # use Logger levels |
||||
# logger.warn "warning message" |
||||
# logger.debug "debug message" |
||||
# |
||||
def initialize(ident = $0, options = Syslog::LOG_PID | Syslog::LOG_CONS, facility = nil) |
||||
@ident = ident |
||||
@options = options || (Syslog::LOG_PID | Syslog::LOG_CONS) |
||||
@facility = facility |
||||
@level = Logger::INFO |
||||
@mutex = Mutex.new |
||||
@formatter = Logger::Formatter.new |
||||
end |
||||
|
||||
%w{debug info warn error fatal unknown}.each do |logger_method| |
||||
# Accepting *args as message could be nil. |
||||
# Default params not supported in ruby 1.8.7 |
||||
define_method logger_method.to_sym do |*args, &block| |
||||
return true if @level > Logger.const_get(logger_method.upcase) |
||||
message = args.first || block && block.call |
||||
add(Logger.const_get(logger_method.upcase), message) |
||||
end |
||||
|
||||
unless logger_method == 'unknown' |
||||
define_method "#{logger_method}?".to_sym do |
||||
@level <= Logger.const_get(logger_method.upcase) |
||||
end |
||||
end |
||||
end |
||||
|
||||
# Log a message at the Logger::INFO level. Useful for use with Rack::CommonLogger |
||||
def write(msg) |
||||
add(Logger::INFO, msg) |
||||
end |
||||
|
||||
# Logs a message at the Logger::INFO level. |
||||
def <<(msg) |
||||
add(Logger::INFO, msg) |
||||
end |
||||
|
||||
# Low level method to add a message. |
||||
# +severity+:: the level of the message. One of Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR, Logger::FATAL, Logger::UNKNOWN |
||||
# +message+:: the message string. |
||||
# If nil, the method will call the block and use the result as the message string. |
||||
# If both are nil or no block is given, it will use the progname as per the behaviour of both the standard Ruby logger, and the Rails BufferedLogger. |
||||
# +progname+:: optionally, overwrite the program name that appears in the log message. |
||||
def add(severity, message = nil, progname = nil, &block) |
||||
if message.nil? && block.nil? && !progname.nil? |
||||
message, progname = progname, nil |
||||
end |
||||
progname ||= @ident |
||||
|
||||
@mutex.synchronize do |
||||
Syslog.open(progname, @options, @facility) do |s| |
||||
s.mask = Syslog::LOG_UPTO(MAPPING[@level]) |
||||
communication = clean(message || block && block.call) |
||||
if self.max_octets |
||||
buffer = "#{tags_text}" |
||||
communication.bytes do |byte| |
||||
buffer.concat(byte) |
||||
# if the last byte we added is potentially part of an escape, we'll go ahead and add another byte |
||||
if buffer.bytesize >= self.max_octets && !['%'.ord,'\\'.ord].include?(byte) |
||||
s.log(MAPPING[severity],buffer) |
||||
buffer = "" |
||||
end |
||||
end |
||||
s.log(MAPPING[severity],buffer) unless buffer.empty? |
||||
else |
||||
s.log(MAPPING[severity],"#{tags_text}#{communication}") |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
# Set the max octets of the messages written to the log |
||||
def max_octets=(max_octets) |
||||
@max_octets = max_octets |
||||
end |
||||
|
||||
# Sets the minimum level for messages to be written in the log. |
||||
# +level+:: one of <tt>Logger::DEBUG</tt>, <tt>Logger::INFO</tt>, <tt>Logger::WARN</tt>, <tt>Logger::ERROR</tt>, <tt>Logger::FATAL</tt>, <tt>Logger::UNKNOWN</tt> |
||||
def level=(level) |
||||
level = Logger.const_get(level.to_s.upcase) if level.is_a?(Symbol) |
||||
|
||||
unless level.is_a?(Fixnum) |
||||
raise ArgumentError.new("Invalid logger level `#{level.inspect}`") |
||||
end |
||||
|
||||
@level = level |
||||
end |
||||
|
||||
# Sets the ident string passed along to Syslog |
||||
def ident=(ident) |
||||
@ident = ident |
||||
end |
||||
|
||||
# Tagging code borrowed from ActiveSupport gem |
||||
def tagged(*tags) |
||||
new_tags = push_tags(*tags) |
||||
yield self |
||||
ensure |
||||
pop_tags(new_tags.size) |
||||
end |
||||
|
||||
def push_tags(*tags) |
||||
tags.flatten.reject{ |i| i.respond_to?(:empty?) ? i.empty? : !i }.tap do |new_tags| |
||||
current_tags.concat new_tags |
||||
end |
||||
end |
||||
|
||||
def pop_tags(size = 1) |
||||
current_tags.pop size |
||||
end |
||||
|
||||
def clear_tags! |
||||
current_tags.clear |
||||
end |
||||
|
||||
protected |
||||
|
||||
# Borrowed from SyslogLogger. |
||||
def clean(message) |
||||
message = message.to_s.dup |
||||
message.strip! # remove whitespace |
||||
message.gsub!(/\n/, '\\n') # escape newlines |
||||
message.gsub!(/%/, '%%') # syslog(3) freaks on % (printf) |
||||
message.gsub!(/\e\[[^m]*m/, '') # remove useless ansi color codes |
||||
message |
||||
end |
||||
|
||||
private |
||||
|
||||
def tags_text |
||||
tags = current_tags |
||||
if tags.any? |
||||
tags.collect { |tag| "[#{tag}] " }.join |
||||
end |
||||
end |
||||
|
||||
def current_tags |
||||
Thread.current[:syslogger_tagged_logging_tags] ||= [] |
||||
end |
||||
end |
||||
listen ENV["UNICORN_PATH"] + "/tmp/sockets/gitlab.socket", :backlog => 1024 |
||||
listen "/run/gitlab/gitlab.socket", :backlog => 1024 |
||||
|
||||
worker_processes 2 |
||||
working_directory ENV["GITLAB_PATH"] |
||||
pid ENV["UNICORN_PATH"] + "/tmp/pids/unicorn.pid" |
||||
|
||||
listen ENV["UNICORN_PATH"] + "/tmp/sockets/gitlab.socket", :backlog => 1024 |
||||
pid ENV["UNICORN_PATH"] + "/tmp/pids/unicorn.pid" |
||||
|
||||
timeout 60 |
||||
|
||||
logger Syslogger.new |
||||
|
||||
# combine Ruby 2.0.0dev or REE with "preload_app true" for memory savings |
||||
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow |
||||
preload_app true |
||||
|
||||
GC.respond_to?(:copy_on_write_friendly=) and |
||||
GC.copy_on_write_friendly = true |
||||
|
||||
check_client_connection false |
||||
|
||||
before_fork do |server, worker| |
||||
# the following is highly recommended for Rails + "preload_app true" |
||||
# as there's no need for the master process to hold a connection |
||||
defined?(ActiveRecord::Base) and |
||||
ActiveRecord::Base.connection.disconnect! |
||||
|
||||
# The following is only recommended for memory/DB-constrained |
||||
# installations. It is not needed if your system can house |
||||
# twice as many worker_processes as you have configured. |
||||
# |
||||
# This allows a new master process to incrementally |
||||
# phase out the old master process with SIGTTOU to avoid a |
||||
# thundering herd (especially in the "preload_app false" case) |
||||
# when doing a transparent upgrade. The last worker spawned |
||||
# will then kill off the old master process with a SIGQUIT. |
||||
old_pid = "#{server.config[:pid]}.oldbin" |
||||
if old_pid != server.pid |
||||
begin |
||||
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU |
||||
Process.kill(sig, File.read(old_pid).to_i) |
||||
rescue Errno::ENOENT, Errno::ESRCH |
||||
end |
||||
end |
||||
|
||||
# Throttle the master from forking too quickly by sleeping. Due |
||||
# to the implementation of standard Unix signal handlers, this |
||||
# helps (but does not completely) prevent identical, repeated signals |
||||
# from being lost when the receiving process is busy. |
||||
# sleep 1 |
||||
end |
||||
|
||||
after_fork do |server, worker| |
||||
# per-process listener ports for debugging/admin/migrations |
||||
# addr = "127.0.0.1:#{9293 + worker.nr}" |
||||
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true) |
||||
|
||||
# the following is *required* for Rails + "preload_app true", |
||||
defined?(ActiveRecord::Base) and |
||||
ActiveRecord::Base.establish_connection |
||||
|
||||
# reset prometheus client, this will cause any opened metrics files to be closed |
||||
defined?(::Prometheus::Client.reinitialize_on_pid_change) && |
||||
Prometheus::Client.reinitialize_on_pid_change |
||||
|
||||
# if preload_app is true, then you may also want to check and |
||||
# restart any other shared sockets/descriptors such as Memcached, |
||||
# and Redis. TokyoCabinet file handles are safe to reuse |
||||
# between any number of forked children (assuming your kernel |
||||
# correctly implements pread()/pwrite() system calls) |
||||
end |
||||
|
Loading…
Reference in new issue