public class LogBiaya {
    static int pesanDibangun = 0;     // penggabungan string di call site
    static int formatDijalankan = 0;  // penggabungan di dalam logger

    public static void main(String[] args) {
        LoggerMini log = new LoggerMini(LevelMini.WARN);

        System.out.println("== Bentuk penggabungan string, TRACE nonaktif ==");
        pesanDibangun = 0;
        for (int i = 1; i <= 3; i++) {
            log.trace("Data ke-" + i + " bernilai " + bangunDetail(i));
        }
        System.out.println("String pesan dibangun  : " + pesanDibangun + " kali");
        System.out.println("Baris yang tercetak    : 0");

        System.out.println();
        System.out.println("== Bentuk parameter {}, TRACE nonaktif ==");
        formatDijalankan = 0;
        for (int i = 1; i <= 3; i++) {
            log.trace("Data ke-{} bernilai {}", i, i * i);
        }
        System.out.println("Operasi format dijalankan: " + formatDijalankan + " kali");

        System.out.println();
        System.out.println("== Level WARN aktif: biaya dibayar hanya saat tercetak ==");
        formatDijalankan = 0;
        log.warn("Stok tinggal {} item", 3);
        System.out.println("Operasi format dijalankan: " + formatDijalankan + " kali");
    }

    static String bangunDetail(int i) {
        pesanDibangun++;
        return String.valueOf(i * i);
    }
}

enum LevelMini { TRACE, DEBUG, INFO, WARN, ERROR }

class LoggerMini {
    private LevelMini ambang;

    LoggerMini(LevelMini ambang) {
        this.ambang = ambang;
    }

    private boolean aktif(LevelMini level) {
        return level.ordinal() >= ambang.ordinal();
    }

    void trace(String pesan) {
        if (aktif(LevelMini.TRACE)) {
            LogBiaya.formatDijalankan++;
            System.out.println("[TRACE] " + pesan);
        }
    }

    void trace(String format, Object a, Object b) {
        if (aktif(LevelMini.TRACE)) {
            LogBiaya.formatDijalankan++;
            System.out.println("[TRACE] " + format
                    .replaceFirst("\\{}", String.valueOf(a))
                    .replaceFirst("\\{}", String.valueOf(b)));
        }
    }

    void warn(String format, Object a) {
        if (aktif(LevelMini.WARN)) {
            LogBiaya.formatDijalankan++;
            System.out.println("[WARN] " + format.replaceFirst("\\{}", String.valueOf(a)));
        }
    }
}
