Skip to content

Commit

Permalink
logging: redo logging configuration
Browse files Browse the repository at this point in the history
- moves logback/log4j to his own module
- simplify module-info maintaince, removed moditect from core
- remove shaded from core
- add unbescape dependency
- javadoc was failing to generate docs because of this issue. fix #3039
- fix #3046
- fix #3047
  • Loading branch information
jknack committed Jul 30, 2023
1 parent 90c4110 commit c297cf3
Show file tree
Hide file tree
Showing 19 changed files with 454 additions and 269 deletions.
40 changes: 0 additions & 40 deletions jooby/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,6 @@

<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<id>fat-jar</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<artifactSet>
<includes>
<include>org.unbescape:*</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>org.unbescape</pattern>
<shadedPattern>${shaded.package}</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>

<!-- sure-fire -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down Expand Up @@ -74,7 +47,6 @@
<dependency>
<groupId>org.unbescape</groupId>
<artifactId>unbescape</artifactId>
<optional>true</optional>
</dependency>

<!-- jakarta.inject -->
Expand All @@ -96,18 +68,6 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<optional>true</optional>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand Down
1 change: 0 additions & 1 deletion jooby/src/etc/module-info.activator

This file was deleted.

2 changes: 1 addition & 1 deletion jooby/src/main/java/io/jooby/Jooby.java
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,7 @@ public static Jooby createApp(

/** Find application.env: */
String logfile =
LogConfigurer.configure(
LoggingService.configure(
provider.getClass().getClassLoader(), new EnvironmentOptions().getActiveNames());
if (logfile != null) {
// Add as property, so we can query where is the log configuration
Expand Down
140 changes: 0 additions & 140 deletions jooby/src/main/java/io/jooby/LogConfigurer.java

This file was deleted.

171 changes: 171 additions & 0 deletions jooby/src/main/java/io/jooby/LoggingService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* Jooby https://jooby.io
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
* Copyright 2014 Edgar Espina
*/
package io.jooby;

import static java.util.Collections.emptyList;

import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.ServiceLoader;

import edu.umd.cs.findbugs.annotations.NonNull;

/**
* Describe the underlying logging system. Jooby provides two implementation: jooby-logback and
* jooby-log4j. You might want to add one of these to your classpath, yet still these are optional.
*
* @since 3.0.1
*/
public interface LoggingService {
/**
* System property to instruct the logging system where the configuration file is. Example: <code>
* logback.configurationFile = ...</code>
*
* @return System property to instruct the logging system where the configuration file is.
*/
String getPropertyName();

/**
* List of possible names for configuration file. Like: <code>logback.xml, log4j.properties, etc..
* </code>.
*
* @return List of possible names for configuration file.
*/
List<String> getLogFileName();

/**
* Utility method to temporarily turn OFF a logger while running an action.
*
* @param logger List of logger names.
* @param task Action to run.
*/
void logOff(List<String> logger, SneakyThrows.Runnable task);

/**
* Initializes the <code>logback.configurationFile</code> system property when a <code>
* logback[.env].xml</code> file is found at <code>user.dir/conf</code> directory or <code>
* user.dir</code>.
*
* <p>Initializes the <code>log4j.configurationFile</code> system property when a <code>
* log4j[.env].[ext]</code> file is found at <code>user.dir/conf</code> directory or <code>
* user.dir</code>. Extension can be one of: <code>.xml</code>, <code>.properties</code>, <code>
* .yaml</code> or <code>.json</code>.
*
* @param classLoader Class loader to use.
* @param names Actives environment names. Useful for choosing an environment specific logging
* configuration file.
*/
static String configure(@NonNull ClassLoader classLoader, @NonNull List<String> names) {
// Supported well-know implementation
String[] keys = {"logback.configurationFile", "log4j.configurationFile"};
for (String key : keys) {
String file = property(key);
if (file != null) {
// Explicitly set, reset and exit
System.setProperty(key, file);
return file;
}
}
var lookup = ServiceLoader.load(LoggingService.class, classLoader).findFirst();
if (lookup.isEmpty()) {
// We could throw an exception here but nope, let user choose any other way of setup logging.
return null;
}
Path userdir = Paths.get(System.getProperty("user.dir"));

var loggingService = lookup.get();
var resources = logFiles(userdir, names, loggingService.getLogFileName());
if (resources.isEmpty()) {
// We could throw an exception here but nope, let user choose any other way of setup logging.
return null;
}

// Check file system:
var logPath =
resources.stream()
.filter(Path.class::isInstance)
.map(Path.class::cast)
.filter(Files::exists)
.findFirst()
.map(Path::toAbsolutePath);
if (logPath.isPresent()) {
System.setProperty(loggingService.getPropertyName(), logPath.toString());
return logPath.toString();
}
// Fallback to classpath:
var logResource =
resources.stream()
.filter(String.class::isInstance)
.map(String.class::cast)
.map(
it -> {
var found = classLoader.getResource(it);
Map.Entry<String, URL> result = null;
if (found != null) {
result = Map.entry(it, found);
}
return result;
})
.filter(Objects::nonNull)
.findFirst();

if (logResource.isPresent()) {
System.setProperty(loggingService.getPropertyName(), logResource.get().getKey());
return logResource.get().getValue().toString();
}
// nothing found
return null;
}

private static List<Object> logFiles(
Path basedir, List<String> profiles, List<String> logFileNames) {
for (String logFileName : logFileNames) {
var extensionStart = logFileName.lastIndexOf('.');
var fileName = logFileName.substring(0, extensionStart);
var fileExt = logFileName.substring(extensionStart);
var files = logFile(basedir, profiles, fileName, fileExt);
if (!files.isEmpty()) {
return files;
}
}
return emptyList();
}

private static List<Object> logFile(
Path basedir, List<String> profiles, String name, String ext) {
Path confdir = basedir.resolve("conf");
List<Object> result = new ArrayList<>();
for (String profile : profiles) {
String logenvfile = name + "." + profile + ext;
// conf/logback.[profile].xml | conf/log4j2.[profile].xml
result.add(confdir.resolve(logenvfile));
// ./logback.[profile].xml | ./log4j2.[profile].xml
result.add(basedir.resolve(logenvfile));
result.add(logenvfile);
}
// fallback: logback.xml | log4j2.xml
String logfile = name + ext;
// conf/logback.xml | conf/log4j2.xml
result.add(confdir.resolve(logfile));
// ./logback.xml | ./log4j2.xml
result.add(basedir.resolve(logfile));

// classpath fallback:
result.add(logfile);

return result;
}

private static String property(String name) {
return System.getProperty(name, System.getenv(name));
}
}
Loading

0 comments on commit c297cf3

Please sign in to comment.