# # logxml.rb # XML File Log Target # # Author:: David Muir # Date:: 10 March 2008 # require 'pipeline/log/erblogtranslator' require 'pipeline/log/log' require 'pipeline/log/rollingdatefileoutputter' require 'pipeline/util/debug' require 'erb' require 'log4r' require 'rexml/document' module Pipeline # # == Description # XML file outputter formatter class. # class XMLFormatter < Log4r::Formatter # This method is invoked automatically by the Log4r system. def format( event ) # If we have trace functionality we are a little more verbose in # our XML output. output = "" message = event.data.gsub( '"', '\'' ).gsub( /\n/, '' ) if ( !event.tracer.nil? ) ti = parse_trace_info( event ) output += "" output += "" output += "" else output += "" end output end #--------------------------------------------------------------------- # Private Methods #--------------------------------------------------------------------- private def parse_trace_info( event ) trace_info = {} matches = /^(.*)\:([0-9]+):in .([A-Za-z0-9_]+)./.match( event.tracer[0] ) if ( ( nil != matches ) and ( matches.size >= 4 ) ) then trace_info[:filename] = matches[1] trace_info[:lineno] = matches[2] trace_info[:function] = matches[3] else trace_info[:filename] = '' trace_info[:lineno] = '-1' trace_info[:function] = '' end # Return our hash with trace information trace_info end end # # == Description # XML File Logger outputter class. # class XMLFileOutputter < Log4r::FileOutputter def initialize( _name, hash={} ) super( _name, hash ) validate_hash( hash ) write_header() # Ensure we close the log at program exit. This ensures we write # the XML footer tags to construct a valid XML document. at_exit { self.close() } end def close begin # Finish XML tags, and close file. write_footer() super() pretty_print() translate_to_html() rescue Exception => ex print_exception( ex ) end end #--------------------------------------------------------------------- # Protected #--------------------------------------------------------------------- protected def write_header( ) @out.write( "" ) @out.write( "" ) end def write_footer( ) @out.write( "" ) end def pretty_print( ) replace_filename = OS::Path.replace_ext( @filename, 'orig' ) FileUtils.cp( @filename, replace_filename ) File.open( replace_filename, "r" ) do |xmlinfile| File.open( @filename, 'w' ) do |xmloutfile| logxml = REXML::Document.new( xmlinfile ) logxml.xml_decl.encoding = "UTF-8" fmt = REXML::Formatters::Pretty.new( ) fmt.write( logxml, xmloutfile ) end end FileUtils.rm( replace_filename ) end def translate_to_html( ) # Setup a XML log translator to translate our log into HTML, if the # user has the generate html log option set. if ( Pipeline::Config.instance.log_generate_html ) then puts "Generating HTML log from #{@filename}..." erb_path = OS::Path.combine( Config.instance.toolsbin, 'pipeline', 'log', 'erb', 'htmllog.erb' ) translator = ErbLogTranslator.new( @filename, erb_path ) translator.translate() translator.save( OS::Path.replace_ext( @filename, 'html' ) ) end end def validate_hash( hash ) super( hash ) @formatter = XMLFormatter.new end end # # == Description # # # class XMLRollingDateFileOutputter < XMLFileOutputter def initialize( _name, hash={} ) super( _name, hash ) @created_at = Time.now @filename_base = OS::Path.get_basename( @filename ) @filename_ext = OS::Path.get_extension( @filename ) end #--------------------------------------------------------------------- # Private Methods #--------------------------------------------------------------------- private def write( data ) roll if requires_roll super end def get_archive_filename() newbase = "#{@filename_base}-#{@created_at.strftime('%Y-%m-%d')}.#{@filename_ext}" OS::Path.combine( OS::Path.get_directory( @filename ), newbase ) end def requires_roll() @created_at.day != Time.now.day end def roll() begin write_footer() @out.close() pretty_print() translate_to_html() archive_filename = get_archive_filename() html_filename = OS::Path.replace_ext( @filename, 'html' ) archive_html_filename = OS::Path.replace_ext( archive_filename, 'html' ) OS::FileUtilsEx.move_file( @filename, archive_filename ) OS::FileUtilsEx.move_file( html_filename, archive_html_filename ) FileUtils.rm( @filename ) FileUtils.rm( html_filename ) rescue Exception => ex Log4r::Logger.log_internal do "XMLRollingDateFileOutputter exception: #{ex.message}" end end @created_at = Time.now @out = File.new( @filename, "w" ) write_header() end end end # Pipeline module # End of logxml.rb