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 021import org.apache.juneau.rest.server.*; 022 023/** 024 * Shared worker for the {@code /loggers} management endpoint: reads and sets logger levels at runtime by 025 * delegating to the {@link LogBackend} resolved from the host context. 026 * 027 * <p> 028 * Both the {@link LoggersMixin mixin} and {@link LoggersResource resource} flavors delegate here, so the 029 * two forms cannot drift — the same pattern the health package uses with its aggregator. 030 * 031 * <h5 class='section'>Backend</h5> 032 * <p> 033 * The driven backend defaults to {@link JulLogBackend java.util.logging}. A consumer drives a different backend 034 * (e.g. Logback / Log4j2 via {@code juneau-rest-server-management-logging}) by <i>explicitly</i> declaring it on a 035 * {@link LoggersSettings} bean via {@link LoggersSettings.Builder#backend(LogBackend)} — the endpoint never 036 * auto-detects. The response shape (logger name → configured level, empty string = inherited) is identical 037 * across backends. 038 * 039 * <h5 class='section'>See Also:</h5><ul> 040 * <li class='jc'>{@link LogBackend} 041 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ManagementSurface">Management Surface (Actuator-style endpoints)</a> 042 * </ul> 043 * 044 * @since 10.0.0 045 */ 046public class LoggersManager { 047 048 /** 049 * Returns a snapshot of all known loggers and their configured levels, for the backend resolved from the 050 * supplied context. 051 * 052 * @param context The REST context whose bean store supplies the {@link LoggersSettings} / {@link LogBackend}. 053 * May be <jk>null</jk> (uses the JUL default). 054 * @return A sorted map of logger name → configured level name (empty string = inherited). Never <jk>null</jk>. 055 */ 056 public Map<String,String> getLevels(RestContext context) { 057 return resolveSettings(context).getBackend().getLevels(); 058 } 059 060 /** 061 * Returns the configured level of a single logger, for the backend resolved from the supplied context. 062 * 063 * @param context The REST context whose bean store supplies the backend. May be <jk>null</jk>. 064 * @param name The logger name ({@code "ROOT"} or empty for the root logger). 065 * @return The configured level name, the empty string if the level is inherited, or <jk>null</jk> if no 066 * such logger is currently registered. 067 */ 068 public String getLevel(RestContext context, String name) { 069 return resolveSettings(context).getBackend().getLevel(name); 070 } 071 072 /** 073 * Sets (or clears) the level of a single logger at runtime (process-lifetime-only), for the backend resolved 074 * from the supplied context. 075 * 076 * @param context The REST context whose bean store supplies the backend. May be <jk>null</jk>. 077 * @param name The logger name ({@code "ROOT"} or empty for the root logger). 078 * @param level The backend-native level name (e.g. {@code "FINE"}/{@code "INFO"} for JUL, 079 * {@code "DEBUG"}/{@code "INFO"} for Logback/Log4j2), or <jk>null</jk>/blank to inherit. 080 * @throws IllegalArgumentException If {@code level} is non-blank but not a valid level name for the backend. 081 */ 082 public void setLevel(RestContext context, String name, String level) { 083 resolveSettings(context).getBackend().setLevel(name, level); 084 } 085 086 /** 087 * Resolves the {@link LoggersSettings} from the host context's bean store, falling back to the 088 * read-only (JUL-backed) default. 089 * 090 * @param context The REST context whose bean store is searched. May be <jk>null</jk>. 091 * @return The registered settings, or {@link LoggersSettings#DEFAULT} when none is registered. 092 */ 093 @SuppressWarnings({ 094 "resource" // The bean store is owned by the RestContext; this adapter only borrows beans and must not close it. 095 }) 096 public LoggersSettings resolveSettings(RestContext context) { 097 if (context == null) 098 return LoggersSettings.DEFAULT; 099 return context.getBeanStore().getBean(LoggersSettings.class).orElse(LoggersSettings.DEFAULT); 100 } 101}