001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.server.management;
018
019import java.util.*;
020
021/**
022 * SPI behind the {@code /loggers} management endpoint: reads and sets logger levels for one concrete logging
023 * backend at runtime.
024 *
025 * <p>
026 * {@code juneau-rest-server} ships only the {@link JulLogBackend java.util.logging} implementation, keeping the
027 * core management surface dependency-free. Support for other backends is opt-in: the
028 * {@code juneau-rest-server-management-logging} add-on ships {@code LogbackLogBackend} / {@code Log4j2LogBackend}
029 * (with the backends declared {@code provided}), and any consumer can implement this interface for a backend
030 * Juneau does not cover.
031 *
032 * <h5 class='topic'>Explicit selection (no auto-drive)</h5>
033 *
034 * <p>
035 * Consistent with Juneau's explicit-over-magic stance, the backend is <b>explicitly declared</b> by registering a
036 * {@link LoggersSettings} bean built with {@link LoggersSettings.Builder#backend(LogBackend)}. When none is
037 * declared, {@link LoggersManager} drives {@link JulLogBackend} &mdash; the endpoint never silently classpath-scans
038 * for, and then drives, a backend the operator didn't choose.
039 *
040 * <h5 class='topic'>Level contract</h5>
041 *
042 * <p>
043 * Levels are exchanged as backend-native level-name strings (e.g. JUL {@code "FINE"}/{@code "INFO"}, Logback /
044 * Log4j2 {@code "DEBUG"}/{@code "INFO"}). Reads report the logger's <b>configured</b> level &mdash; the level set
045 * on the logger itself, or the empty string when it inherits from an ancestor. Sets are
046 * <b>process-lifetime-only</b> (they do not rewrite the backend's configuration file). The root logger is
047 * addressed under the key {@code "ROOT"}.
048 *
049 * <h5 class='section'>See Also:</h5><ul>
050 *    <li class='jc'>{@link JulLogBackend}
051 *    <li class='jc'>{@link LoggersManager}
052 *    <li class='jc'>{@link LoggersSettings}
053 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ManagementSurface">Management Surface (Actuator-style endpoints)</a>
054 * </ul>
055 *
056 * @since 10.0.0
057 */
058public interface LogBackend {
059
060   /**
061    * Returns a snapshot of all known loggers and their configured levels.
062    *
063    * @return A sorted map of logger name &rarr; configured level name (empty string = inherited from an
064    *    ancestor). The root logger is keyed {@code "ROOT"}. Never <jk>null</jk>.
065    */
066   Map<String,String> getLevels();
067
068   /**
069    * Returns the configured level of a single logger.
070    *
071    * @param name The logger name ({@code "ROOT"} or empty for the root logger).
072    * @return The configured level name, the empty string if the level is inherited, or <jk>null</jk> if no such
073    *    logger is currently registered.
074    */
075   String getLevel(String name);
076
077   /**
078    * Sets (or clears) the level of a single logger at runtime (process-lifetime-only).
079    *
080    * @param name The logger name ({@code "ROOT"} or empty for the root logger).
081    * @param level The backend-native level name, or <jk>null</jk>/blank to clear the logger's own level so it
082    *    inherits from its ancestor.
083    * @throws IllegalArgumentException If {@code level} is non-blank but not a valid level name for the backend.
084    */
085   void setLevel(String name, String level);
086}