sirve settitle que para java logging

settitle - ¿Cómo cambio la salida de la consola de registro java de std err a std out?



para que sirve settitle en java (12)

ConsoleHandler obtendrá una instantánea de System.err durante la construcción. Una opción sería intercambiar la secuencia de error global con la salida global y luego crear ConsoleHandler.

ConsoleHandler h = null; final PrintStream err = System.err; System.setErr(System.out); try { h = new ConsoleHandler(); //Snapshot of System.err } finally { System.setErr(err); }

Esto supone que el código tiene permiso para modificar la secuencia de errores y que ningún otro código en ejecución está accediendo a la secuencia de errores. En resumen, esta es una opción, pero hay alternativas más seguras.

Estoy utilizando el ConsoleHandler estándar de java.util.logging y, de forma predeterminada, la salida de la consola se dirige a la secuencia de errores (es decir, System.err ).

¿Cómo cambio la salida de la consola a la secuencia de salida (es decir, System.out )?


Cuando creamos un nuevo objeto ConsoleHandler, la secuencia de salida predeterminada es "system.err". Desafortunadamente, Java no proporciona ningún método público para que la clase ConsoleHandler establezca el flujo de salida. Por lo tanto, se puede establecer solo en el momento de la creación del objeto. Como la clase ConsoleHandler extiende StreamHandler, que tiene un método protegido "setOutputStream" para establecer la secuencia de salida explícitamente. Para configurar la salida Stream para ConsoleHandler, simplemente anule este método en el momento de la nueva llamada para la creación de objetos.

ConsoleHandler consoleHandler = new ConsoleHandler (){ @Override protected synchronized void setOutputStream(OutputStream out) throws SecurityException { super.setOutputStream(System.out); } };


Eche un vistazo a los documentos y la fuente de ConsoleHandler : estoy seguro de que podría escribir fácilmente una versión que solo use System.err en lugar de System.out. (Es una pena que ConsoleHandler no permita que esto se configure, para ser honesto).

Entonces, solo es un caso de configuración del sistema de registro para usar su nuevo StdoutHandler (o como se llame) de la manera normal.


He llegado a

SimpleFormatter fmt = new SimpleFormatter(); StreamHandler sh = new StreamHandler(System.out, fmt); logger.addHandler(sh);


Hmm, me pique un poco en el pie varias veces, tratando de lograr esta hazaña. Antes de googlear mi camino, logré conjurar el siguiente truco. Feo, pero parece hacer el trabajo.

public class StdoutConsoleHandler extends ConsoleHandler { protected void setOutputStream(OutputStream out) throws SecurityException { super.setOutputStream(System.out); // kitten killed here :-( } }

Cuidado: Llamar a setOutputStream () desde el constructor es tentador, pero lo hace (como Jon Skeet ya señaló) cierre System.err. ¡Habilidades locas!


Me di cuenta de una manera. Primero elimine el controlador de consola predeterminado:

setUseParentHandlers (falso);

Luego subclase ConsoleHandler y en el constructor:

setOutputStream (System.out);


Si configura setUseParentHandlers (falso); solo esa clase lo tiene configurado. Otras clases en la aplicación todavía lo pasarán a stderr.


Si todavía hay alguien por ahí buscando una solución a este problema. Esto es lo que finalmente se me ocurrió: acabo de subclasificar StreamHandler y agregué un parámetro adicional MaxLevel, que se comprueba al comienzo de publish (). Si el nivel del evento de registro es mayor que MaxLevel, la publicación no se ejecutará más. Aquí están los detalles:

MaxlevelStreamHandler.java Main Class a continuación.

package helper; /** * The only difference to the standard StreamHandler is * that a MAXLEVEL can be defined (which then is not published) * * @author Kai Goergen */ import java.io.PrintStream; import java.util.logging.Formatter; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.StreamHandler; public class MaxlevelStreamHandler extends StreamHandler { private Level maxlevel = Level.SEVERE; // by default, put out everything /** * The only method we really change to check whether the message * is smaller than maxlevel. * We also flush here to make sure that the message is shown immediately. */ @Override public synchronized void publish(LogRecord record) { if (record.getLevel().intValue() > this.maxlevel.intValue()) { // do nothing if the level is above maxlevel } else { // if we arrived here, do what we always do super.publish(record); super.flush(); } } /** * getter for maxlevel * @return */ public Level getMaxlevel() { return maxlevel; } /** * Setter for maxlevel. * If a logging event is larger than this level, it won''t be displayed * @param maxlevel */ public void setMaxlevel(Level maxlevel) { this.maxlevel = maxlevel; } /** Constructor forwarding */ public MaxlevelStreamHandler(PrintStream out, Formatter formatter) { super(out, formatter); } /** Constructor forwarding */ public MaxlevelStreamHandler() { super(); } }

Clase principal

Para mostrar ahora algunos eventos en stdout y algunos en stderr, simplemente configure dos StreamLoggers, uno para eventos críticos y uno para todos los demás, y deshabilite el registrador de consola estándar:

// setup all logs that are smaller than WARNINGS to stdout MaxlevelStreamHandler outSh = new MaxlevelStreamHandler(System.out, formatter); outSh.setLevel(Level.ALL); outSh.setMaxlevel(Level.INFO); logger.addHandler(outSh); // setup all warnings to stdout & warnings and higher to stderr StreamHandler errSh = new StreamHandler(System.err, formatter); errSh.setLevel(Level.WARNING); logger.addHandler(errSh); // remove default console logger logger.setUseParentHandlers(false); logger.info("info"); logger.warning("warning"); logger.severe("severe");

¡Espero que esto ayude!

Actualización: agregué super.flush () justo después de super.publish () para asegurarme de que el mensaje se muestra inmediatamente. Antes, tenía problemas con los mensajes de registro que siempre se mostraban al final. Ahora es parte del código anterior.


Si usa el registro de Java, puede cambiar el controlador predeterminado:

Por ejemplo, para archivos: Handler fh = new FileHandler (FILENAME); Logger.getLogger (LOGGER_NAME) .addHandler (fh);

Si desea exportar a una transmisión, puede usar StreamHandler, creo que puede configurarlo con cualquier flujo de salida que desee, incluida la transmisión del sistema.


Simplemente extienda StreamHandler & en la llamada del constructor Super (System.out,). Esto evitará cerrar System.err - Gracias


Tuve un problema similar. Quería registrar INFO y debajo en System.out , y WARNING y arriba en System.err . Aquí está la solución que implementé:

public class DualConsoleHandler extends StreamHandler { private final ConsoleHandler stderrHandler = new ConsoleHandler(); public DualConsoleHandler() { super(System.out, new SimpleFormatter()); } @Override public void publish(LogRecord record) { if (record.getLevel().intValue() <= Level.INFO.intValue()) { super.publish(record); super.flush(); } else { stderrHandler.publish(record); stderrHandler.flush(); } } }

Por supuesto, podría hacerlo más flexible factorizando la referencia codificada a Level.INFO , por ejemplo. Pero esto funcionó bien para obtener un registro básico de doble flujo. (Por cierto, los consejos sobre la no subclasificación de ConsoleHandler para evitar el cierre de System.err fueron muy útiles).


Handler consoleHandler = new Handler(){ @Override public void publish(LogRecord record) { if (getFormatter() == null) { setFormatter(new SimpleFormatter()); } try { String message = getFormatter().format(record); if (record.getLevel().intValue() >= Level.WARNING.intValue()) { System.err.write(message.getBytes()); } else { System.out.write(message.getBytes()); } } catch (Exception exception) { reportError(null, exception, ErrorManager.FORMAT_FAILURE); } } @Override public void close() throws SecurityException {} @Override public void flush(){} };