Hi,
This attachments fix the most obvious flaw in my submission: The class
names ended in Logger instead of Appender.
Thanks for your patience,
Markus
--
markus schaber | dipl. informatiker
logi-track ag | rennweg 14-16 | ch 8001 z�rich
phone +41-43-888 62 52 | fax +41-43-888 62 53
mailto:[EMAIL PROTECTED] | www.logi-track.com
/*
* Logger Command Appender Class
*
* $Id: MultipipeLogger.java,v 1.1 2004/04/08 10:52:05 schabi Exp $
*
* (C) 2004 Markus Schaber, logi-track ag, Z�rich, Switzerland.
*
* Submitted for inclusion into the apache.org log4j project, Copyright (C) The
* Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package com.logitrack.sql.posinsertdaemon.log;
import java.io.IOException;
import org.apache.log4j.Appender;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Layout;
import org.apache.log4j.Logger;
import org.apache.log4j.WriterAppender;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;
/**
* MultipipeLogger - allows to log via syslog "logger" command or other
* processes that log stdin.
*
* CAVEATS: Currently, when a pipe breaks, some log events will be lost until
* successful restart of the pipe process, including the event that triggered
* the successful recreation, and as it uses WriterAppenders internally, it
* blocks when the pipe is full.
*
* @author Markus Schaber, logi-track ag, Z�rich, Switzerland.
*
*/
public class MultipipeAppender extends AppenderSkeleton {
protected String pipeCommand;
protected String facility;
protected final WriterAppender[] writers = new WriterAppender[8];
protected final Process[] processes = new Process[8];
protected final BrokenPipeHandler[] recreatePipes = new BrokenPipeHandler[8];
boolean badcallmessage = true;
private static final String[] levels = new String[] { "crit", "crit", "crit", "error", "warning", "warning",
"info", "debug"};
/**
* simple constructor.
*
* You have to set layout, pipecommand and facility and then call
* activateOptions() before you can use it.
*/
public MultipipeAppender() {
super();
for (int i = 0; i < recreatePipes.length; i++) {
recreatePipes[i] = new BrokenPipeHandler(i);
}
}
/**
* This constructor produces an ready-to-use MultipipeLogger.
*
* @param layout
* @param pipecommand
* @param facility
*/
public MultipipeAppender(Layout layout, String pipecommand, String facility) {
this();
super.setLayout(layout);
this.pipeCommand = pipecommand;
this.facility = facility;
this.activateOptions();
}
protected void append(LoggingEvent event) {
int pri = event.getLevel().getSyslogEquivalent();
if (pri < 0) {
pri = 0;
} else if (pri >= writers.length) {
pri = writers.length - 1;
}
if (writers[pri] == null) { //We try to reinstantiate logger
activateWriter(pri);
}
if (writers[pri] != null) { //maybe reinstantiation was not successfull
writers[pri].doAppend(event);
}
}
/**
* Close this appenders - tries to stop all processes
*/
public synchronized void close() {
if (closed) {
return;
}
for (int i = 0; i < writers.length; i++) {
close(i);
}
closed = true;
}
/**
* Derived appenders should override this method if option structure
* requires it.
*/
public synchronized void activateOptions() {
close();
for (int i = 0; i < writers.length; i++) {
activateWriter(i);
}
closed = false;
}
protected void close(int i) {
Process process = processes[i];
if (writers[i] != null) {
writers[i].close();
writers[i] = null;
}
if (process != null) {
try {
process.getOutputStream().close();
} catch (IOException E) {
LogLog.warn("Error closing Stream for " + levels[i], E);
}
try {
process.waitFor();
} catch (InterruptedException E) {
LogLog.warn("Error closing Process for " + levels[i], E);
}
processes[i] = null;
}
}
protected void activateWriter(int i) {
try {
if ((i > 0) && (levels[i - 1].equals(levels[i])) && (writers[i - 1] != null)) {
writers[i] = writers[i - 1];
processes[i] = processes[i - 1];
} else {
Process p = Runtime.getRuntime().exec(createCommandString(i));
processes[i] = p;
writers[i] = new WriterAppender(layout, p.getOutputStream());
writers[i].setErrorHandler(recreatePipes[i]);
}
} catch (IOException E) {
LogLog.error("Cannot open pipe for " + levels[i], E);
}
}
/**
* @param i
* @return
*/
private String createCommandString(int i) {
return pipeCommand + " " + facility + "." + levels[i];
}
/*
* (non-Javadoc)
*
* @see org.apache.log4j.Appender#requiresLayout()
*/
public boolean requiresLayout() {
return true;
}
/**
* Bean Getter for pipeCommand
*
* @return The content of pipeCommand.
*/
public String getPipeCommand() {
return pipeCommand;
}
/**
* Bean Setter for pipeCommand
*
* @param pipeCommand The new value for pipeCommand.
*/
public void setPipeCommand(String pipeCommand) {
this.pipeCommand = pipeCommand;
}
/**
* Bean Getter for facility
*
* @return The content of facility.
*/
public String getFacility() {
return facility;
}
/**
* Bean Setter for facility
*
* @param facility The new value for facility.
*/
public void setFacility(String facility) {
this.facility = facility;
}
/**
* BrokenPipeHandler is triggered when the internally used WriterAppenders
* fail, and it tries to recreate the broken pipes again.
*/
protected class BrokenPipeHandler implements org.apache.log4j.spi.ErrorHandler {
private int index;
/**
* default constructor
*
* @param i The index of our Writer
*/
protected BrokenPipeHandler(int i) {
this.index = i;
}
public void setLogger(Logger logger) {
// ignored
}
public void error(String message) {
LogLog.warn("Error '" + message + " occured. Trying to recreate MultipipeLogger pipe " + index);
recover();
}
public void error(String message, Exception e, int errorCode) {
LogLog.warn("Error '" + message + "' occured with Errorcode " + errorCode
+ ".\nTrying to recreate MultipipeLogger pipe " + index, e);
recover();
}
public void error(String message, Exception e, int errorCode, LoggingEvent event) {
LogLog.warn("Logging Event " + e + " caused a logging error:");
error(message, e, errorCode);
}
private void recover() {
try {
close(index);
activateWriter(index);
} catch (Exception E) {
LogLog.debug("Error while trying to recover from Broken Pipe Error", E);
}
}
public void setAppender(Appender appender) {
// ignored
}
public void setBackupAppender(Appender appender) {
// ignored
}
public void activateOptions() {
//ignored
}
}
}/*
* MultipipeLoggerTester.java Created on 08.04.2004 11:53:03 by schabi
*
* $Id: MultipipeLoggerTester.java,v 1.1 2004/04/08 10:52:05 schabi Exp $
*
* (C) 2004 Markus Schaber, logi-track ag, Z�rich, Switzerland.
*
* Submitted for inclusion into the apache.org log4j project, Copyright (C) The
* Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package com.logitrack.sql.posinsertdaemon.log;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
/**
* Test class for the multipipe Logger.
*
* It is not easy to create a sensible unit test for this as there is no easy,
* platform-independent way to read the written syslogs back :-/
*
* @author Markus Schaber, logi-track ag, Z�rich, Switzerland.
*
*/
public class MultipipeAppenderTester {
/**
* Shell commant to test MultipipeLogger
*
* @param args
*/
public static void main(String[] args) {
System.out.println("Initializing Loging System");
MultipipeAppender app = new MultipipeAppender(new org.apache.log4j.PatternLayout(
org.apache.log4j.PatternLayout.TTCC_CONVERSION_PATTERN), "/usr/bin/logger -p", "user");
app.setThreshold(Level.ALL);
BasicConfigurator.configure(app);
Logger log = Logger.getLogger(MultipipeAppenderTester.class);
System.out.println("Simple logging tests");
log.debug("Debug log test");
log.info("Info log test");
log.warn("Warn log test");
log.error("Error log test");
log.fatal("Fatal log test");
System.out.println("Failed backend recovety test");
log.debug("Going to destroy logging backend 7");
app.processes[7].destroy();
log.debug("First message after destruction - will get lost");
log.debug("Second message after destruction - should reach syslog");
System.out.println("Finished - now visit your syslog files to see the results.");
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]