1# The following was taken from github.com/crohr/syslogger and is BSD 2# licensed. 3require 'syslog' 4require 'logger' 5require 'thread' 6 7class Syslogger 8 9 VERSION = "1.6.0" 10 11 attr_reader :level, :ident, :options, :facility, :max_octets 12 attr_accessor :formatter 13 14 MAPPING = { 15 Logger::DEBUG => Syslog::LOG_DEBUG, 16 Logger::INFO => Syslog::LOG_INFO, 17 Logger::WARN => Syslog::LOG_WARNING, 18 Logger::ERROR => Syslog::LOG_ERR, 19 Logger::FATAL => Syslog::LOG_CRIT, 20 Logger::UNKNOWN => Syslog::LOG_ALERT 21 } 22 23 # 24 # Initializes default options for the logger 25 # <tt>ident</tt>:: the name of your program [default=$0]. 26 # <tt>options</tt>:: syslog options [default=<tt>Syslog::LOG_PID | Syslog::LOG_CONS</tt>]. 27 # Correct values are: 28 # LOG_CONS : writes the message on the console if an error occurs when sending the message; 29 # LOG_NDELAY : no delay before sending the message; 30 # LOG_PERROR : messages will also be written on STDERR; 31 # LOG_PID : adds the process number to the message (just after the program name) 32 # <tt>facility</tt>:: the syslog facility [default=nil] Correct values include: 33 # Syslog::LOG_DAEMON 34 # Syslog::LOG_USER 35 # Syslog::LOG_SYSLOG 36 # Syslog::LOG_LOCAL2 37 # Syslog::LOG_NEWS 38 # etc. 39 # 40 # Usage: 41 # logger = Syslogger.new("my_app", Syslog::LOG_PID | Syslog::LOG_CONS, Syslog::LOG_LOCAL0) 42 # logger.level = Logger::INFO # use Logger levels 43 # logger.warn "warning message" 44 # logger.debug "debug message" 45 # 46 def initialize(ident = $0, options = Syslog::LOG_PID | Syslog::LOG_CONS, facility = nil) 47 @ident = ident 48 @options = options || (Syslog::LOG_PID | Syslog::LOG_CONS) 49 @facility = facility 50 @level = Logger::INFO 51 @mutex = Mutex.new 52 @formatter = Logger::Formatter.new 53 end 54 55 %w{debug info warn error fatal unknown}.each do |logger_method| 56 # Accepting *args as message could be nil. 57 # Default params not supported in ruby 1.8.7 58 define_method logger_method.to_sym do |*args, &block| 59 return true if @level > Logger.const_get(logger_method.upcase) 60 message = args.first || block && block.call 61 add(Logger.const_get(logger_method.upcase), message) 62 end 63 64 unless logger_method == 'unknown' 65 define_method "#{logger_method}?".to_sym do 66 @level <= Logger.const_get(logger_method.upcase) 67 end 68 end 69 end 70 71 # Log a message at the Logger::INFO level. Useful for use with Rack::CommonLogger 72 def write(msg) 73 add(Logger::INFO, msg) 74 end 75 76 # Logs a message at the Logger::INFO level. 77 def <<(msg) 78 add(Logger::INFO, msg) 79 end 80 81 # Low level method to add a message. 82 # +severity+:: the level of the message. One of Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR, Logger::FATAL, Logger::UNKNOWN 83 # +message+:: the message string. 84 # If nil, the method will call the block and use the result as the message string. 85 # 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. 86 # +progname+:: optionally, overwrite the program name that appears in the log message. 87 def add(severity, message = nil, progname = nil, &block) 88 if message.nil? && block.nil? && !progname.nil? 89 message, progname = progname, nil 90 end 91 progname ||= @ident 92 93 @mutex.synchronize do 94 Syslog.open(progname, @options, @facility) do |s| 95 s.mask = Syslog::LOG_UPTO(MAPPING[@level]) 96 communication = clean(message || block && block.call) 97 if self.max_octets 98 buffer = "#{tags_text}" 99 communication.bytes do |byte| 100 buffer.concat(byte) 101 # if the last byte we added is potentially part of an escape, we'll go ahead and add another byte 102 if buffer.bytesize >= self.max_octets && !['%'.ord,'\\'.ord].include?(byte) 103 s.log(MAPPING[severity],buffer) 104 buffer = "" 105 end 106 end 107 s.log(MAPPING[severity],buffer) unless buffer.empty? 108 else 109 s.log(MAPPING[severity],"#{tags_text}#{communication}") 110 end 111 end 112 end 113 end 114 115 # Set the max octets of the messages written to the log 116 def max_octets=(max_octets) 117 @max_octets = max_octets 118 end 119 120 # Sets the minimum level for messages to be written in the log. 121 # +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> 122 def level=(level) 123 level = Logger.const_get(level.to_s.upcase) if level.is_a?(Symbol) 124 125 unless level.is_a?(Fixnum) 126 raise ArgumentError.new("Invalid logger level `#{level.inspect}`") 127 end 128 129 @level = level 130 end 131 132 # Sets the ident string passed along to Syslog 133 def ident=(ident) 134 @ident = ident 135 end 136 137 # Tagging code borrowed from ActiveSupport gem 138 def tagged(*tags) 139 new_tags = push_tags(*tags) 140 yield self 141 ensure 142 pop_tags(new_tags.size) 143 end 144 145 def push_tags(*tags) 146 tags.flatten.reject{ |i| i.respond_to?(:empty?) ? i.empty? : !i }.tap do |new_tags| 147 current_tags.concat new_tags 148 end 149 end 150 151 def pop_tags(size = 1) 152 current_tags.pop size 153 end 154 155 def clear_tags! 156 current_tags.clear 157 end 158 159 protected 160 161 # Borrowed from SyslogLogger. 162 def clean(message) 163 message = message.to_s.dup 164 message.strip! # remove whitespace 165 message.gsub!(/\n/, '\\n') # escape newlines 166 message.gsub!(/%/, '%%') # syslog(3) freaks on % (printf) 167 message.gsub!(/\e\[[^m]*m/, '') # remove useless ansi color codes 168 message 169 end 170 171 private 172 173 def tags_text 174 tags = current_tags 175 if tags.any? 176 tags.collect { |tag| "[#{tag}] " }.join 177 end 178 end 179 180 def current_tags 181 Thread.current[:syslogger_tagged_logging_tags] ||= [] 182 end 183end 184 185worker_processes 2 186working_directory ENV["GITLAB_PATH"] 187pid ENV["UNICORN_PATH"] + "/tmp/pids/unicorn.pid" 188 189listen ENV["UNICORN_PATH"] + "/tmp/sockets/gitlab.socket", :backlog => 1024 190 191timeout 60 192 193logger Syslogger.new 194 195preload_app true 196 197GC.respond_to?(:copy_on_write_friendly=) and 198 GC.copy_on_write_friendly = true 199 200check_client_connection false 201 202after_fork do |server, worker| 203 defined?(ActiveRecord::Base) and 204 ActiveRecord::Base.establish_connection 205end