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.microservice.jetty;
018
019import static java.util.logging.Level.*;
020import static org.apache.juneau.commons.utils.Utils.*;
021
022import java.util.logging.*;
023import java.util.logging.Logger;
024
025import org.slf4j.*;
026import org.slf4j.spi.*;
027
028/**
029 * Implementation of Jetty {@link Logger} based on {@link java.util.logging.Logger}.
030 *
031 * <p>
032 * Allows Jetty to log to the Java Util logging framework (and thus to the main log file defined in the
033 * <cc>[Logging]</cc> section).
034 *
035 * <p>
036 * Can be used by setting the following system property in the microservice config file.
037 *
038 * <p class='bini'>
039 *    <cs>[SystemProperties]</cs>
040 *
041 *    <cc># Configure Jetty to log using java-util logging</cc>
042 *    <ck>org.eclipse.jetty.util.log.class</ck> = org.apache.juneau.microservice.jetty.JettyLogger
043 * </p>
044 *
045 * <h5 class='section'>See Also:</h5><ul>
046 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauMicroserviceJettyBasics">juneau-microservice-jetty Basics</a>
047 * </ul>
048 */
049public class JettyLogger implements LocationAwareLogger {
050   private static final boolean SHOW_SOURCE = env("org.eclipse.jetty.util.log.SOURCE", env("org.eclipse.jetty.util.log.javautil.SOURCE", true));
051
052   /**
053    * Formats a log message by replacing "{}" placeholders with the provided arguments.
054    *
055    * @param msg The message template with "{}" placeholders.
056    * @param args The arguments to substitute into the message.
057    * @return The formatted message string.
058    */
059   private static String format(String msg, Object...args) {
060      return f(msg, args);
061   }
062
063   /**
064    * The originally configured log level, used to restore the level when debug mode is disabled.
065    */
066   private Level configuredLevel;
067
068   /**
069    * The underlying Java Util Logger instance.
070    */
071   private Logger logger;
072
073   /**
074    * Default constructor.
075    *
076    * <p>
077    * Returns the logger with name <js>"org.eclipse.jetty.util.log.javautil"</js>.
078    */
079   public JettyLogger() {
080      this("org.eclipse.jetty.util.log.javautil");
081   }
082
083   /**
084    * Normal constructor.
085    *
086    * @param name The logger name.
087    */
088   public JettyLogger(String name) {
089      logger = Logger.getLogger(name);
090      configuredLevel = logger.getLevel();
091   }
092
093   @Override
094   public void debug(Marker marker, String msg) {
095      // TODO Auto-generated method stub
096
097   }
098
099   @Override
100   public void debug(Marker marker, String format, Object arg) {
101      // TODO Auto-generated method stub
102
103   }
104
105   @Override
106   public void debug(Marker marker, String format, Object...arguments) {
107      // TODO Auto-generated method stub
108
109   }
110
111   @Override
112   public void debug(Marker marker, String format, Object arg1, Object arg2) {
113      // TODO Auto-generated method stub
114
115   }
116
117   @Override
118   public void debug(Marker marker, String msg, Throwable t) {
119      // TODO Auto-generated method stub
120
121   }
122
123   @Override
124   public void debug(String msg) {
125      // TODO Auto-generated method stub
126
127   }
128
129   /**
130    * Logs a debug message with a long argument.
131    *
132    * @param msg The message template with "{}" placeholder.
133    * @param arg The long argument to substitute into the message.
134    */
135   public void debug(String msg, long arg) {
136      if (isLoggable(FINE))
137         log(FINE, format(msg, arg), null);
138   }
139
140   @Override
141   public void debug(String msg, Object...args) {
142      if (isLoggable(FINE))
143         log(FINE, format(msg, args), null);
144   }
145
146   @Override
147   public void debug(String format, Object arg) {
148      // TODO Auto-generated method stub
149
150   }
151
152   @Override
153   public void debug(String format, Object arg1, Object arg2) {
154      // TODO Auto-generated method stub
155
156   }
157
158   @Override
159   public void debug(String msg, Throwable thrown) {
160      if (isLoggable(FINE))
161         log(FINE, msg, thrown);
162   }
163
164   /**
165    * Logs a debug message with only a throwable.
166    *
167    * @param thrown The throwable to log.
168    */
169   public void debug(Throwable thrown) {
170      if (isLoggable(FINE))
171         log(FINE, "", thrown);
172   }
173
174   @Override
175   public void error(Marker marker, String msg) {
176      // TODO Auto-generated method stub
177   }
178
179   @Override
180   public void error(Marker marker, String format, Object arg) {
181      // TODO Auto-generated method stub
182   }
183
184   @Override
185   public void error(Marker marker, String format, Object...arguments) {
186      // TODO Auto-generated method stub
187   }
188
189   @Override
190   public void error(Marker marker, String format, Object arg1, Object arg2) {
191      // TODO Auto-generated method stub
192   }
193
194   @Override
195   public void error(Marker marker, String msg, Throwable t) {
196      // TODO Auto-generated method stub
197   }
198
199   @Override
200   public void error(String msg) {
201      // TODO Auto-generated method stub
202   }
203
204   @Override
205   public void error(String format, Object arg) {
206      // TODO Auto-generated method stub
207   }
208
209   @Override
210   public void error(String format, Object...arguments) {
211      // TODO Auto-generated method stub
212   }
213
214   @Override
215   public void error(String format, Object arg1, Object arg2) {
216      // TODO Auto-generated method stub
217   }
218
219   @Override
220   public void error(String msg, Throwable t) {
221      // TODO Auto-generated method stub
222   }
223
224   /**
225    * Creates a child logger with the specified name.
226    *
227    * @param name The logger name.
228    * @return A new JettyLogger instance for the specified name.
229    */
230   public JettyLogger getLogger(String name) {
231      return new JettyLogger(name);
232   }
233
234   @Override
235   public String getName() { return logger.getName(); }
236
237   /**
238    * Logs an ignored exception at the FINEST level.
239    *
240    * @param ignored The exception to log as ignored.
241    */
242   public void ignore(Throwable ignored) {
243      if (isLoggable(FINEST))
244         log(FINEST, "IGNORED EXCEPTION ", ignored);
245   }
246
247   @Override
248   public void info(Marker marker, String msg) {
249      // TODO Auto-generated method stub
250   }
251
252   @Override
253   public void info(Marker marker, String format, Object arg) {
254      // TODO Auto-generated method stub
255
256   }
257
258   @Override
259   public void info(Marker marker, String format, Object...arguments) {
260      // TODO Auto-generated method stub
261   }
262
263   @Override
264   public void info(Marker marker, String format, Object arg1, Object arg2) {
265      // TODO Auto-generated method stub
266   }
267
268   @Override
269   public void info(Marker marker, String msg, Throwable t) {
270      // TODO Auto-generated method stub
271
272   }
273
274   @Override
275   public void info(String msg) {
276      // TODO Auto-generated method stub
277   }
278
279   @Override
280   public void info(String msg, Object...args) {
281      if (isLoggable(INFO))
282         log(INFO, format(msg, args), null);
283   }
284
285   @Override
286   public void info(String format, Object arg) {
287      // TODO Auto-generated method stub
288   }
289
290   @Override
291   public void info(String format, Object arg1, Object arg2) {
292      // TODO Auto-generated method stub
293   }
294
295   @Override
296   public void info(String msg, Throwable thrown) {
297      if (isLoggable(INFO))
298         log(INFO, msg, thrown);
299   }
300
301   /**
302    * Logs an info message with only a throwable.
303    *
304    * @param thrown The throwable to log.
305    */
306   public void info(Throwable thrown) {
307      if (isLoggable(INFO))
308         log(INFO, "", thrown);
309   }
310
311   @Override
312   public boolean isDebugEnabled() { return isLoggable(FINE); }
313
314   @Override
315   public boolean isDebugEnabled(Marker marker) {
316      // TODO Auto-generated method stub
317      return false;
318   }
319
320   @Override
321   public boolean isErrorEnabled() {
322      // TODO Auto-generated method stub
323      return false;
324   }
325
326   @Override
327   public boolean isErrorEnabled(Marker marker) {
328      // TODO Auto-generated method stub
329      return false;
330   }
331
332   @Override
333   public boolean isInfoEnabled() {
334      // TODO Auto-generated method stub
335      return false;
336   }
337
338   @Override
339   public boolean isInfoEnabled(Marker marker) {
340      // TODO Auto-generated method stub
341      return false;
342   }
343
344   @Override
345   public boolean isTraceEnabled() {
346      // TODO Auto-generated method stub
347      return false;
348   }
349
350   @Override
351   public boolean isTraceEnabled(Marker marker) {
352      // TODO Auto-generated method stub
353      return false;
354   }
355
356   @Override
357   public boolean isWarnEnabled() {
358      // TODO Auto-generated method stub
359      return false;
360   }
361
362   @Override
363   public boolean isWarnEnabled(Marker marker) {
364      // TODO Auto-generated method stub
365      return false;
366   }
367
368   @Override
369   public void log(Marker marker, String fqcn, int level, String message, Object[] argArray, Throwable t) {
370      // TODO Auto-generated method stub
371   }
372
373   /**
374    * Enables or disables debug logging.
375    *
376    * <p>
377    * When enabled, sets the log level to FINE. When disabled, restores the previously configured log level.
378    *
379    * @param enabled <jk>true</jk> to enable debug logging, <jk>false</jk> to disable.
380    */
381   public void setDebugEnabled(boolean enabled) {
382      if (enabled) {
383         configuredLevel = logger.getLevel();
384         logger.setLevel(FINE);
385      } else {
386         logger.setLevel(configuredLevel);
387      }
388   }
389
390   @Override
391   public void trace(Marker marker, String msg) {
392      // TODO Auto-generated method stub
393
394   }
395
396   @Override
397   public void trace(Marker marker, String format, Object arg) {
398      // TODO Auto-generated method stub
399
400   }
401
402   @Override
403   public void trace(Marker marker, String format, Object...argArray) {
404      // TODO Auto-generated method stub
405
406   }
407
408   @Override
409   public void trace(Marker marker, String format, Object arg1, Object arg2) {
410      // TODO Auto-generated method stub
411
412   }
413
414   @Override
415   public void trace(Marker marker, String msg, Throwable t) {
416      // TODO Auto-generated method stub
417
418   }
419
420   @Override
421   public void trace(String msg) {
422      // TODO Auto-generated method stub
423
424   }
425
426   @Override
427   public void trace(String format, Object arg) {
428      // TODO Auto-generated method stub
429
430   }
431
432   @Override
433   public void trace(String format, Object...arguments) {
434      // TODO Auto-generated method stub
435
436   }
437
438   @Override
439   public void trace(String format, Object arg1, Object arg2) {
440      // TODO Auto-generated method stub
441
442   }
443
444   @Override
445   public void trace(String msg, Throwable t) {
446      // TODO Auto-generated method stub
447
448   }
449
450   @Override
451   public void warn(Marker marker, String msg) {
452      // TODO Auto-generated method stub
453   }
454
455   @Override
456   public void warn(Marker marker, String format, Object arg) {
457      // TODO Auto-generated method stub
458   }
459
460   @Override
461   public void warn(Marker marker, String format, Object...arguments) {
462      // TODO Auto-generated method stub
463   }
464
465   @Override
466   public void warn(Marker marker, String format, Object arg1, Object arg2) {
467      // TODO Auto-generated method stub
468   }
469
470   @Override
471   public void warn(Marker marker, String msg, Throwable t) {
472      // TODO Auto-generated method stub
473   }
474
475   @Override
476   public void warn(String msg) {
477      // TODO Auto-generated method stub
478   }
479
480   @Override
481   public void warn(String msg, Object...args) {
482      if (isLoggable(WARNING))
483         log(WARNING, format(msg, args), null);
484   }
485
486   @Override
487   public void warn(String format, Object arg) {
488      // TODO Auto-generated method stub
489   }
490
491   @Override
492   public void warn(String format, Object arg1, Object arg2) {
493      // TODO Auto-generated method stub
494
495   }
496
497   @Override
498   public void warn(String msg, Throwable thrown) {
499      if (isLoggable(WARNING))
500         log(WARNING, msg, thrown);
501   }
502
503   /**
504    * Logs a warning message with only a throwable.
505    *
506    * @param thrown The throwable to log.
507    */
508   public void warn(Throwable thrown) {
509      if (isLoggable(WARNING))
510         log(WARNING, "", thrown);
511   }
512
513   /**
514    * Checks if a message at the specified level would be logged.
515    *
516    * @param level The log level to check.
517    * @return <jk>true</jk> if the level is loggable, <jk>false</jk> otherwise.
518    */
519   private boolean isLoggable(Level level) {
520      return logger.isLoggable(level);
521   }
522
523   /**
524    * Internal log method that creates a LogRecord and logs it.
525    *
526    * <p>
527    * Optionally includes source class and method name in the log record if SHOW_SOURCE is enabled.
528    *
529    * @param level The log level.
530    * @param msg The log message.
531    * @param thrown The throwable to log, or <jk>null</jk> if none.
532    */
533   private void log(Level level, String msg, Throwable thrown) {
534      var r = new LogRecord(level, msg);
535      if (nn(thrown))
536         r.setThrown(thrown);
537      r.setLoggerName(logger.getName());
538      if (SHOW_SOURCE) {
539         StackTraceElement[] stack = new Throwable().getStackTrace();
540         for (var e : stack) {
541            if (! e.getClassName().equals(getClass().getName())) {
542               r.setSourceClassName(e.getClassName());
543               r.setSourceMethodName(e.getMethodName());
544               break;
545            }
546         }
547      }
548      logger.log(r);
549   }
550}