Log.java

package com.shengzhiai.yugu.internal;

import com.shengzhiai.yugu.LogLevel;
import com.shengzhiai.yugu.YuguLogger;

import java.io.PrintStream;
import java.time.Instant;

/** Level filter in front of the configured sink. Sink failures are swallowed. */
public final class Log {
    private final LogLevel level;
    private final YuguLogger sink;

    /**
     * @param level threshold
     * @param sink  sink, null for standard error
     */
    public Log(LogLevel level, YuguLogger sink) {
        this.level = level == null ? LogLevel.WARN : level;
        this.sink = sink == null ? Log::console : sink;
    }

    /** @return true when DEBUG messages are written */
    public boolean isDebug() {
        return level.allows(LogLevel.DEBUG);
    }

    /** @return true when INFO messages are written */
    public boolean isInfo() {
        return level.allows(LogLevel.INFO);
    }

    /**
     * @param l   level
     * @param tag tag
     * @param msg message
     * @param err error or null
     */
    public void log(LogLevel l, String tag, String msg, Throwable err) {
        if (!level.allows(l)) {
            return;
        }
        try {
            sink.log(l, tag, msg, err);
        } catch (RuntimeException ignored) {
            // a broken sink must not break the SDK
        }
    }

    /** @param tag tag @param msg message */
    public void debug(String tag, String msg) {
        log(LogLevel.DEBUG, tag, msg, null);
    }

    /** @param tag tag @param msg message */
    public void info(String tag, String msg) {
        log(LogLevel.INFO, tag, msg, null);
    }

    /** @param tag tag @param msg message @param err error or null */
    public void warn(String tag, String msg, Throwable err) {
        log(LogLevel.WARN, tag, msg, err);
    }

    /** @param tag tag @param msg message @param err error or null */
    public void error(String tag, String msg, Throwable err) {
        log(LogLevel.ERROR, tag, msg, err);
    }

    static void console(LogLevel level, String tag, String message, Throwable error) {
        PrintStream out = System.err;
        StringBuilder sb = new StringBuilder(96);
        sb.append(Instant.now()).append(' ').append(level).append(" [yugu/").append(tag).append("] ").append(message);
        if (error != null) {
            sb.append(": ").append(error);
        }
        out.println(sb);
    }
}