Posts Tagged ‘snippets’
Kleine Ruby Logger Klasse
Normalerweise sind die Artikel hier ja ziemlich umfangreich, was ja auch gut ist schließlich geht das Sixserv Blog ja schon sehr ins technische Detail. Doch diesmal wird es eher kurz, ich möchte eine kleine Logger Klasse vorstellen die ich in Ruby geschrieben habe und seither häufiger benutze.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | class Logger def self.init @logfile = LOG_FILE @buffer = [] # logging lines for buffering end def self.<< msg msg = format msg # append message to buffer @buffer << msg # flush the buffer if possible self.flush end def self.flush return if @buffer.empty? # try to lock the file for writing log = File.new(@logfile, 'a+') if log.flock(File::LOCK_EX | File::LOCK_NB) == false # Logfile is locked puts "Logfile is locked!" log.close return false end # ==> not locked, write buffer to logfile while @buffer.length > 0 log.puts @buffer.shift end log.flock(File::LOCK_UN) log.close end private def self.format msg time = Time.now.strftime '%H:%M:%S - %d.%m.%Y' "[#{time}] #{msg}" end end |
Nichts großes also, es gibt z.B. keine Log-Level usw. Außerdem kann man sich, wenn man etwas mehr Features braucht, auch eine Logging Bibliothek aus dem Gems bedienen. Die Anwendung ist ganz einfach:
1 2 3 4 5 6 7 8 | require '/pfad/zu/logger.rb' Logger.init # das kann man dann überall im Code verteilen: Logger << "Irgendeine Nachricht!" # hat man eine große Anwendung mit vielen Prozessen/Threads # kann man auch an strategischen Stellen ein Logger.flush # einbauen :) |
Hier noch eine kleine Erweiterung die einen Log-Server implementiert. Er öffnet einen TCP Port, jeder der sich verbindet(z.B. per Telnet/Netcat) kann daraufhin die Log-Nachrichten mitlesen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | class Logger def self.init ... @port = LOG_PORT @query = [] @query_mutex = nil @running = false @server = nil end def self.start_server @query_mutex = Mutex.new puts "Start logging console @ #{LOG_HOST}:#{LOG_PORT}" @server = TCPServer.new(LOG_HOST, LOG_PORT) clients = [] @running = true Thread.start do client = [] while @running do begin client = @server.accept_nonblock clients << client if client != nil rescue end begin message = nil @query_mutex.synchronize { message = @query.pop } if message != nil clients.each do |client| begin client.puts message rescue clients.delete client end end end end while not @query.empty? sleep LOG_SERVER_INTERVAL end clients.each { |client| client.close } @server.close @server = nil end end def self.destroy @running = false @fs.close # wait until server closed true while @server != nil end def self.<< msg if @query_mutex != nil @query_mutex.synchronize do @query << format(msg) end end puts ">>> #{msg}" end def self.flush # just wait until everything is sent/written if @query.length > 0 true while @query.length != 0 end end ... end |
So das wars schon, ich hoffe das ich das mit dem Mutex richtig gemacht habe und das hier überhaupt notwendig war, ich habe auf dem Gebiet nicht viel Erfahrung und würde mich über einen entsprechenden Kommentar freuen.
// I’m not sure I used the Mutex in this example correctly, I would appreciate a comment about this.