如何在logging.properties

时间:2019-02-27 16:09:00

标签: java.util.logging

当前,我所有的INFO,SEVERE和FINE日志都以红色打印。我想将INFO和FINE日志更改为白色。

我发现许多文章通过创建新的Fommater来改变颜色。我想知道如何通过修改logging.properties来更改打印颜色?

我正在使用Java默认日志记录库Util.Logging.Logger

环境:

  • Ecipse 2018-12(4.10.0)
  • Windows 10

3 个答案:

答案 0 :(得分:1)

  

当前,我所有的INFO,SEVERE和FINE日志都以红色打印。

这取决于正在消耗System.err的进程。 Since the output is red I assume you are using an IDE。您正在使用哪个IDE?也许它具有修改控制台输出呈现方式的设置。对于日食,您可以:

  1. 更改Standard Out/Standard Error text color,以使标准输出为白色,标准错误为红色。
  2. 创建一个设置为警告级别的常规ConsoleHandler。这会将所有警告及以上警告定向到ERR流,该流将为红色。
  3. 创建特殊的Handler to print to Standard OUT并将级别设置为ALL。
  4. 为标准OUT处理程序创建一个java.util.logging.Filter来过滤出大于INFO的消息,并将其安装在该处理程序上。
  5. 将控制台处理程序(ERR)和OUT处理程序都附加到根记录器。
  

我想知道如何通过修改logging.properties来更改打印颜色?

您只能从logging.properties中执行的操作是安装一种新型的Formatter或第3方处理程序,该处理程序可以更改输出颜色,但是这取决于所使用的控制台输出流的呈现方式(例如,EG HTML与BASH终端)。

答案 1 :(得分:0)

问题是Eclipse总是以相同的颜色(在这种情况下为红色)显示stderr输出。它可以在设置中进行配置,但对于所有stderr流,它始终是相同的。

我的解决方案是为控制台处理程序使用自定义格式程序,并根据每条消息的级别在每条消息之前注入ANSI颜色代码。因此,我基于JDK8中的原始SimpleFormatter.java做到了这一点。这是代码:

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;

public class CustomFormatter extends Formatter {

    public static final String ANSI_RESET = "\u001B[0m";
    public static final String ANSI_RED = "\u001B[31m";
    public static final String ANSI_YELLOW = "\u001B[33m";
    public static final String ANSI_CYAN = "\u001B[36m";

    private final Date dat = new Date();
    private static final String format = "%1$s %2$tb %2$td, %2$tY %2$tl:%2$tM:%2$tS %2$Tp %3$s%n%5$s: %6$s%7$s%n";

    @Override
    public String format(LogRecord record) {
        dat.setTime(record.getMillis());
        String source;
        if (record.getSourceClassName() != null) {
            source = record.getSourceClassName();
            if (record.getSourceMethodName() != null) {
                source += " " + record.getSourceMethodName();
            }
        } else {
            source = record.getLoggerName();
        }
        String message = formatMessage(record);
        String throwable = "";
        if (record.getThrown() != null) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            pw.println();
            record.getThrown().printStackTrace(pw);
            pw.close();
            throwable = sw.toString();
        }

        switch (record.getLevel().toString()) {
            case "INFO":
                return String.format(format, ANSI_CYAN, dat, source, record.getLoggerName(),
                        record.getLevel().getLocalizedName(), message + ANSI_RESET, throwable);
            case "WARNING":
                return String.format(format, ANSI_YELLOW, dat, source, record.getLoggerName(),
                        record.getLevel().getLocalizedName(), message + ANSI_RESET, throwable);
            case "SEVERE":
                return String.format(format, ANSI_RED, dat, source, record.getLoggerName(),
                        record.getLevel().getLocalizedName(), message + ANSI_RESET, throwable);
            default:
                return String.format(format, dat, source, record.getLoggerName(),
                        record.getLevel().getLocalizedName(), message, throwable);
        }
    }
}

先决条件

  • ANSI Escape in Console plugin(用于Eclipse)。您将需要使用它,以便Eclipse控制台可以解释ANSI Escape代码。 安装并重新启动Eclipse

  • 上面的代码已编译并压缩为 .jar文件

    1. 将上面的代码另存为CustomFormatter.java
    2. 使用javac CustomFormatter.java
    3. 进行编译
    4. 使用jar cfv CustomFormatter.jar CustomFormatter.class创建一个包含类文件的JAR文件,并将其保存在所需的任何文件夹中(例如,在C:\java\CustomFormatter中)

说明

  • 转到Window --> Preferences --> Ansi Console并选中Try using the standard error color setting for stderr output,然后选择Apply and Close
  • 编辑logging.properties 文件,该文件位于JRE的lib文件夹中。您的计算机中可能有多个,您应编辑与Eclipse使用的JRE版本相对应的一个。通过阅读Eclipse中“控制台”选项卡下面的信息,您可以知道正在使用哪个:JRE folder

    1. 使用文本编辑器打开logging.properties。就我而言,我将编辑C:\Program Files\Java\jre1.8.0_231\lib\logging.properties
    2. 您应该更改java.util.logging.ConsoleHandler.formatter的值(在我的情况下是第44行),使其等于CustomFormatter完全像这样:java.util.logging.ConsoleHandler.formatter = CustomFormatter 。确保保存更改。
  • CustomFormatter.jar添加为Eclipse中的JRE系统库

    1. 转到Window --> Preferences --> Java --> Installed JREs
    2. 选择您正在使用的JRE,单击EditAdd External JARs...
    3. 转到保存CustomFormatter.jar的文件夹并选择它。
    4. 确保它在系统库列表中,然后单击FinishApply and Close
    5. 就是这样。您现在应该为每个Logger级别使用不同的颜色。 INFO为青色,WARNING为黄色,SEVERE为红色。您可以使用corresponding ANSI Color code修改上面的代码,将其更改为所需的颜色。它适用于Java 8和Eclipse 2019-12:

      Result

注意::如果正常的标准输出文本显示为蓝色,红色或黄色,请尝试禁用Limit console output中的Window --> Preferences --> Run/Debug --> Console

答案 2 :(得分:0)

来自 jajube 的精彩回答。我使用 netbeans 8.2。它的控制台有默认的红色文本,但处理 ANSI 代码。我修改了他对下面格式化程序的回答

#include <iostream>
#include <chrono>
#include <gmp.h>
#include <string>

bool mpz_is_divisible(mpz_t n, mpz_t d);

void mpz_sqr(mpz_t res, mpz_t x) {
   //computes square of x and puts the result into res

   mpz_pow_ui(res, x, 2);
}

//the below function causes stack overflow for large inputs

void smallest_divisor(mpz_t n, mpz_t div, mpz_t div_sqr, mpz_t smallest_div) {
 //finds the smallest number which divides n and puts the result into smallest_div

  mpz_sqr(div_sqr, div);
  
  if (mpz_cmp(div_sqr, n) > 0) {
     mpz_set(smallest_div, n);
     return;
  }

  if (mpz_is_divisible(n, div)) {
    mpz_set(smallest_div, div);
    return;
  }

  mpz_add_ui(div, div, 1);
  smallest_divisor(n, div, div_sqr, smallest_div); //<-- should do tail recursion optimisation?
}

bool mpz_prime_test_basic(mpz_t n) {
  //checks if n is prime

  mpz_t div, div_sqr, smallest_div;

  mpz_inits(div, div_sqr, smallest_div, NULL);
  mpz_set_ui(div, 2);

  smallest_divisor(n, div, div_sqr, smallest_div);

  if (mpz_cmp(smallest_div, n) == 0) {
    mpz_clear(div);
    mpz_clear(div_sqr);
    mpz_clear(smallest_div);
    return true;
  }
  mpz_clear(div);
  mpz_clear(div_sqr);
  mpz_clear(smallest_div);
  return false;
}

bool mpz_is_divisible(mpz_t n, mpz_t d) {
  //checks if n is divisible by d
  mpz_t rem;
  mpz_init(rem);
  mpz_tdiv_r(rem, n, d);
  int cmp = mpz_cmp_si(rem, 0); //checks if remainder is equal to 0
  if (cmp == 0) return true;
  return false;
}

int main() {
  std::string num_str;
  mpz_t num;
  mpz_init(num);
  std::cout << "Enter number to check" << '\n';
  std::cin >> num_str;
  mpz_set_str(num, num_str.c_str(), 10);

  bool is_prime = mpz_prime_test_basic(num);

  if (is_prime) {
    std::cout << num_str << " is a prime\n";
  } else {
    std::cout << num_str << " is not a prime\n";
  }

  return 0;
}

它在我在启动时指定的 Logging.properties 中实例化

package net.sf.jaer.util;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;

/**
 * Based on
 * https://stackoverflow.com/questions/54909752/how-to-change-the-util-logging-logger-printing-colour-in-logging-properties
 * with ANSI codes from
 * https://stackoverflow.com/questions/5762491/how-to-print-color-in-console-using-system-out-println
 *
 * @author tobid Jan 2021
 */
public class LoggingAnsiColorConsoleFormatter extends Formatter {

    public static final String ANSI_RESET = "\u001B[0m";
    public static final String ANSI_BLACK = "\u001B[30m";
    public static final String ANSI_RED = "\u001B[31m";
    public static final String ANSI_GREEN = "\u001B[32m";
    public static final String ANSI_YELLOW = "\u001B[33m";
    public static final String ANSI_BLUE = "\u001B[34m";
    public static final String ANSI_PURPLE = "\u001B[35m";
    public static final String ANSI_CYAN = "\u001B[36m";
    public static final String ANSI_WHITE = "\u001B[37m";
    public static final String ANSI_BLACK_BACKGROUND = "\u001B[40m";
    public static final String ANSI_RED_BACKGROUND = "\u001B[41m";
    public static final String ANSI_GREEN_BACKGROUND = "\u001B[42m";
    public static final String ANSI_YELLOW_BACKGROUND = "\u001B[43m";
    public static final String ANSI_BLUE_BACKGROUND = "\u001B[44m";
    public static final String ANSI_PURPLE_BACKGROUND = "\u001B[45m";
    public static final String ANSI_CYAN_BACKGROUND = "\u001B[46m";
    public static final String ANSI_WHITE_BACKGROUND = "\u001B[47m";

    private final Date date = new Date();
    // FORMAT uses e.g. 2$ which refers to 2nd argument of String.format
    // It has two lines: Line 1 is the date and class/method. Line 2 is the LEVEL and message
    // Lines are separated by the format spec %n which makes newline
    // This format puts date and class/method in CYAN, followed by newline with level colored, followed by default message color
    private static final String FORMAT = ANSI_CYAN+"%2$tb %2$td, %2$tY %2$tl:%2$tM:%2$tS %2$Tp %3$s%n%1$s%5$s:" + ANSI_RESET + " %6$s%7$s%n";
    // args to String.format
    // 1 ansi code
    // 2 date 
    // 3 source (class/method) 
    // 4 logger name 
    // 5 level 
    // 6 message, 
    // 7 throwable
    // output example
    // Jan 05, 2021 7:09:55 AM net.sf.jaer.eventprocessing.filter.BackgroundActivityFilter resetFilter
    //INFO: resetting BackgroundActivityFilter

    @Override
    public String format(LogRecord record) {
        date.setTime(record.getMillis());
        String source;
        if (record.getSourceClassName() != null) {
            source = record.getSourceClassName();
            if (record.getSourceMethodName() != null) {
                source += " " + record.getSourceMethodName();
            }
        } else {
            source = record.getLoggerName();
        }
        String message = formatMessage(record);
        String throwable = "";
        if (record.getThrown() != null) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            pw.println();
            record.getThrown().printStackTrace(pw);
            pw.close();
            throwable = sw.toString();
        }

        switch (record.getLevel().toString()) {
            case "INFO":
                return String.format(FORMAT, ANSI_GREEN_BACKGROUND+ANSI_BLACK, date, source, record.getLoggerName(),
                        record.getLevel().getLocalizedName(), message + ANSI_RESET, throwable);
            case "WARNING":
                return String.format(FORMAT, ANSI_YELLOW_BACKGROUND+ANSI_BLACK, date, source, record.getLoggerName(),
                        record.getLevel().getLocalizedName(), message + ANSI_RESET, throwable);
            case "SEVERE":
                return String.format(FORMAT, ANSI_RED_BACKGROUND + ANSI_WHITE, date, source, record.getLoggerName(),
                        record.getLevel().getLocalizedName(), message + ANSI_RESET, throwable);
            default:
                return String.format(FORMAT, date, source, record.getLoggerName(),
                        record.getLevel().getLocalizedName(), message, throwable);
        }
    }
}

Logging.properties 有这一行

-Djava.util.logging.config.file=conf/Logging.properties

输出是这样的

console logger sample