Ленивая оценка сообщения журнала в Java - PullRequest
0 голосов
/ 02 июля 2018

В некоторых случаях мне интересно отложить создание сообщения журнала, поэтому оно не будет создано в случае, если уровень журнала недостаточен.

Я делаю это, передавая обратный вызов в функцию ведения журнала, которая вызывается, если уровень ведения журнала достаточен.

Проблема в том, что я не могу передать переменную, которая не является окончательно эффективной из-за ограничений закрытия, которые есть в Java.

Как это сделать чище?

Рабочий код: http://tpcg.io/IspNlN

import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.function.Supplier;

public class StackOverflow
{
    private static final int LOG_LEVEL=2;
    private static final int TRACE_LEVEL=0;

    private static void trace(Supplier<String> messageCallback){
        if(TRACE_LEVEL>LOG_LEVEL) return;
        System.out.println(messageCallback.get());          
    }

    private static void foo(){      
        for(int i=0; i<10; i++){
            doSomething();
            int finalI=i; //I need it because of "Local variable parameterIndex defined in an enclosing scope must be final or effectively final"
            trace(()->"FLOW-1: "+getHugeString()+" for i:"+finalI);
        }
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        foo();
    }

    private static  void doSomething(){
        //some operation
    }

    private static String getHugeString(){          
        return "A huge string that took much time to create";
    }
}

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

У вас есть три варианта, упомянутых в порядке предпочтения.

Вариант 1

Используйте правильную библиотеку журналов.

Вариант 2, как указано @ Glains

private static boolean isTraceEnabled()
{
    return TRACE_LEVEL <= LOG_LEVEL;
}

private static void trace(String msg)
{
    if (isTraceEnabled())
    {
        System.out.println(msg);
    }
}

private static void foo()
{
    for (int i = 0; i < 10; i++)
    {
        doSomething();
        if (isTraceEnabled())
        {
            trace("FLOW-1: " + getHugeString() + " for i:" + i);
        }
    }
}

Вариант 3: использовать формат сообщения, как в jdk logger.

private static void trace(String format, Object... values)
{
    if (TRACE_LEVEL > LOG_LEVEL)
    {
        return;
    }
    for (int i = 0; i < values.length; i++)
    {
        Object value = values[i];
        if (value instanceof Supplier)
        {
            values[i] = ((Supplier) value).get();
        }
    }
    System.out.println(new MessageFormat(format).format(values));
}

вызов как

trace("FLOW-1: {0} for i: {1}", (Supplier) (StackOverflow::getHugeString), i);
0 голосов
/ 02 июля 2018

Обычные каркасы ведения журналов предлагают методы, такие как isDebugEnabled или isInfoEnabled, чтобы точно защитить от того случая, когда создание строк может занять больше времени.

if(LOG.isDebugEnabled()) {
    LOG.debug("Some objects toString method called: {}", someObject.toString());
}

Кроме того, ваш метод также работает, но имеет ограничения, которые вы уже указали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...