001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.microservice; 014 015import static java.util.logging.Level.*; 016import java.util.logging.*; 017 018import org.apache.juneau.internal.*; 019import org.eclipse.jetty.util.log.AbstractLogger; 020 021/** 022 * Implementation of Jetty {@link Logger} based on {@link java.util.logging.Logger}. 023 * 024 * <p> 025 * Allows Jetty to log to the Java Util logging framework (and thus to the main log file defined in the 026 * <cc>[Logging]</cc> section). 027 * 028 * <p> 029 * Can be used by setting the following system property in the microservice config file. 030 * 031 * <p class='bcode'> 032 * <cs>[SystemProperties]</cs> 033 * 034 * <cc># Configure Jetty to log using java-util logging</cc> 035 * <ck>org.eclipse.jetty.util.log.class</ck> = org.apache.juneau.microservice.JettyLogger 036 * </p> 037 * 038 */ 039public class JettyLogger extends AbstractLogger { 040 private static final boolean SHOW_SOURCE = SystemUtils.getFirstBoolean(true, "org.eclipse.jetty.util.log.SOURCE", "org.eclipse.jetty.util.log.javautil.SOURCE"); 041 042 private Level configuredLevel; 043 private Logger logger; 044 045 /** 046 * Default constructor. 047 * 048 * <p> 049 * Returns the logger with name <js>"org.eclipse.jetty.util.log.javautil"</js>. 050 */ 051 public JettyLogger() { 052 this("org.eclipse.jetty.util.log.javautil"); 053 } 054 055 /** 056 * Normal constructor. 057 * 058 * @param name The logger name. 059 */ 060 public JettyLogger(String name) { 061 logger = Logger.getLogger(name); 062 configuredLevel = logger.getLevel(); 063 } 064 065 @Override 066 public String getName() { 067 return logger.getName(); 068 } 069 070 @Override 071 public void warn(String msg, Object... args) { 072 if (isLoggable(WARNING)) 073 log(WARNING, format(msg, args), null); 074 } 075 076 @Override 077 public void warn(Throwable thrown) { 078 if (isLoggable(WARNING)) 079 log(WARNING, "", thrown); 080 } 081 082 @Override 083 public void warn(String msg, Throwable thrown) { 084 if (isLoggable(WARNING)) 085 log(WARNING, msg, thrown); 086 } 087 088 @Override 089 public void info(String msg, Object... args) { 090 if (isLoggable(INFO)) 091 log(INFO, format(msg, args), null); 092 } 093 094 @Override 095 public void info(Throwable thrown) { 096 if (isLoggable(INFO)) 097 log(INFO, "", thrown); 098 } 099 100 @Override 101 public void info(String msg, Throwable thrown) { 102 if (isLoggable(INFO)) 103 log(INFO, msg, thrown); 104 } 105 106 @Override 107 public boolean isDebugEnabled() { 108 return isLoggable(FINE); 109 } 110 111 @Override 112 public void setDebugEnabled(boolean enabled) { 113 if (enabled) { 114 configuredLevel = logger.getLevel(); 115 logger.setLevel(FINE); 116 } else { 117 logger.setLevel(configuredLevel); 118 } 119 } 120 121 @Override 122 public void debug(String msg, Object... args) { 123 if (isLoggable(FINE)) 124 log(FINE, format(msg, args), null); 125 } 126 127 @Override 128 public void debug(String msg, long arg) { 129 if (isLoggable(FINE)) 130 log(FINE, format(msg, arg), null); 131 } 132 133 @Override 134 public void debug(Throwable thrown) { 135 if (isLoggable(FINE)) 136 log(FINE, "", thrown); 137 } 138 139 @Override 140 public void debug(String msg, Throwable thrown) { 141 if (isLoggable(FINE)) 142 log(FINE, msg, thrown); 143 } 144 145 @Override 146 protected org.eclipse.jetty.util.log.Logger newLogger(String fullname) { 147 return new JettyLogger(fullname); 148 } 149 150 @Override 151 public void ignore(Throwable ignored) { 152 if (isLoggable(FINEST)) 153 log(FINEST, org.eclipse.jetty.util.log.Log.IGNORED, ignored); 154 } 155 156 private static String format(String msg, Object... args) { 157 msg = String.valueOf(msg); 158 if (args.length == 0) 159 return msg; 160 StringBuilder sb = new StringBuilder(); 161 int start = 0; 162 for (Object arg : args) { 163 int bi = msg.indexOf("{}", start); 164 if (bi < 0) { 165 sb.append(msg.substring(start)).append(" ").append(arg); 166 start = msg.length(); 167 } else { 168 sb.append(msg.substring(start, bi)).append(String.valueOf(arg)); 169 start = bi + 2; 170 } 171 } 172 sb.append(msg.substring(start)); 173 return sb.toString(); 174 } 175 176 private void log(Level level, String msg, Throwable thrown) { 177 LogRecord r = new LogRecord(level, msg); 178 if (thrown != null) 179 r.setThrown(thrown); 180 r.setLoggerName(logger.getName()); 181 if (SHOW_SOURCE) { 182 StackTraceElement[] stack = new Throwable().getStackTrace(); 183 for (int i = 0; i < stack.length; i++) { 184 StackTraceElement e = stack[i]; 185 if (!e.getClassName().equals(getClass().getName())) { 186 r.setSourceClassName(e.getClassName()); 187 r.setSourceMethodName(e.getMethodName()); 188 break; 189 } 190 } 191 } 192 logger.log(r); 193 } 194 195 private boolean isLoggable(Level level) { 196 return logger.isLoggable(level); 197 } 198}