feat: switch loggers to System.Logger and update dependencies
ci/woodpecker/push/docs Pipeline was successful Details
ci/woodpecker/push/jfmod Pipeline was successful Details

This commit is contained in:
Johannes Frohnmeyer 2024-03-14 16:01:39 +01:00
parent 580a74fee8
commit 7080cfbff2
Signed by: Johannes
GPG Key ID: E76429612C2929F4
22 changed files with 279 additions and 190 deletions

View File

@ -5,20 +5,11 @@ plugins {
allprojects { group = "io.gitlab.jfronny.libjf" }
subprojects { version = rootProject.version }
val fabricVersion by extra("0.91.1+1.20.4")
val commonsVersion by extra("1.5-SNAPSHOT")
val gsonCompileVersion by extra("1.4-SNAPSHOT")
val modmenuVersion by extra("9.0.0-pre.1")
val annotationsVersion by extra("24.0.1")
val javapoetVersion by extra("1.13.0")
val baseCommonsModules by extra(listOf("http-client", "io", "logging", "logging-slf4j", "serialize", "serialize-gson"))
jfMod {
minecraftVersion = "1.20.4"
yarn("build.1")
loaderVersion = "0.15.0"
minecraftVersion = libs.versions.minecraft
yarn(libs.versions.yarn.get())
fabricLoaderVersion = libs.versions.fabric.loader
fabricApiVersion = libs.versions.fabric.api
modrinth {
projectId = "libjf"
@ -38,12 +29,11 @@ allprojects {
}
dependencies {
modLocalRuntime("com.terraformersmc:modmenu:$modmenuVersion") {
modLocalRuntime(libs.modmenu) {
exclude("net.fabricmc") // required to work around duplicate fabric loaders
}
modLocalRuntime(fabricApi.module("fabric-command-api-v2", fabricVersion))
modLocalRuntime(fabricApi.module("fabric-networking-api-v1", fabricVersion))
compileOnly("io.gitlab.jfronny:commons:$commonsVersion")
baseCommonsModules.forEach { compileOnly("io.gitlab.jfronny:commons-$it:$commonsVersion") }
modLocalRuntime("net.fabricmc.fabric-api:fabric-command-api-v2")
modLocalRuntime("net.fabricmc.fabric-api:fabric-networking-api-v1")
compileOnly(libs.bundles.commons)
}
}

27
gradle/libs.versions.toml Normal file
View File

@ -0,0 +1,27 @@
# jf-scripts version is in settings.gradle.kts
[versions]
minecraft = "1.20.4"
yarn = "build.3"
fabric-loader = "0.15.7"
fabric-api = "0.96.4+1.20.4"
jf-commons = "1.6-SNAPSHOT"
modmenu = "9.0.0"
gson-compile = "1.4-SNAPSHOT"
annotations = "24.1.0"
javapoet = "1.13.0"
[libraries]
commons = { module = "io.gitlab.jfronny:commons", version.ref="jf-commons" }
commons-http-client = { module = "io.gitlab.jfronny:commons-http-client", version.ref="jf-commons" }
commons-io = { module = "io.gitlab.jfronny:commons-io", version.ref="jf-commons" }
commons-logger = { module = "io.gitlab.jfronny:commons-logger", version.ref="jf-commons" }
commons-serialize = { module = "io.gitlab.jfronny:commons-serialize", version.ref="jf-commons" }
commons-serialize-gson = { module = "io.gitlab.jfronny:commons-serialize-gson", version.ref="jf-commons" }
commons-unsafe = { module = "io.gitlab.jfronny:commons-unsafe", version.ref="jf-commons" }
modmenu = { module = "com.terraformersmc:modmenu", version.ref="modmenu" }
gson-compile-processor-core = { module = "io.gitlab.jfronny.gson:gson-compile-processor-core", version.ref="gson-compile" }
annotations = { module = "org.jetbrains:annotations", version.ref="annotations" }
javapoet = { module = "com.squareup:javapoet", version.ref="javapoet" }
[bundles]
commons = ["commons", "commons-http-client", "commons-logger", "commons-io", "commons-serialize", "commons-serialize-gson"]

View File

@ -1,3 +1,8 @@
import com.github.jengelman.gradle.plugins.shadow.transformers.ServiceFileTransformer
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
import org.codehaus.plexus.util.IOUtil
import java.io.ByteArrayOutputStream
plugins {
id("jfmod.module")
}
@ -7,12 +12,24 @@ base {
}
dependencies {
val fabricVersion: String by rootProject.extra
val commonsVersion: String by rootProject.extra
val baseCommonsModules: List<String> by rootProject.extra
include(modImplementation(fabricApi.module("fabric-lifecycle-events-v1", fabricVersion))!!)
shadow("io.gitlab.jfronny:commons:$commonsVersion")
baseCommonsModules.forEach { shadow("io.gitlab.jfronny:commons-$it:$commonsVersion") {
if (it == "logging-slf4j") isTransitive = false
} }
include(modImplementation("net.fabricmc.fabric-api:fabric-lifecycle-events-v1")!!)
shadow(libs.bundles.commons)
}
// workaround to ensure our custom System.LoggerFinder is initialized early
// ideally, we would use the configuration API, but that seems to cause a class loading issue with fabric loader
tasks.shadowJar {
val path = "META-INF/services/java.lang.System\$LoggerFinder"
val field = ServiceFileTransformer::class.java.getDeclaredField("serviceEntries").apply { isAccessible = true }
exclude(path)
transform(object: ServiceFileTransformer() {
private val serviceEntries get() = field.get(this) as MutableMap<String, Any>
override fun transform(context: TransformerContext?) {
super.transform(context)
(serviceEntries[path] as ByteArrayOutputStream).run {
reset()
file("src/main/resources/$path").inputStream().use { IOUtil.copy(it, this) }
}
}
})
}

View File

@ -1,21 +1,20 @@
package io.gitlab.jfronny.libjf;
import io.gitlab.jfronny.commons.logging.Level;
import io.gitlab.jfronny.commons.logging.Logger;
import io.gitlab.jfronny.commons.logging.slf4j.SLF4JLogger;
import io.gitlab.jfronny.commons.logger.HotswapLoggerFinder;
import io.gitlab.jfronny.commons.logger.SystemLoggerPlus;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders;
import io.gitlab.jfronny.libjf.gson.HiddenAnnotationExclusionStrategy;
import net.fabricmc.loader.api.FabricLoader;
import io.gitlab.jfronny.libjf.log.SLF4JPlatformLogger;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
import org.slf4j.LoggerFactory;
public class LibJf implements PreLaunchEntrypoint {
public static final String MOD_ID = "libjf";
public static final Logger LOGGER = Logger.forName(MOD_ID);
public static final SystemLoggerPlus LOGGER = SystemLoggerPlus.forName(MOD_ID);
static {
HiddenAnnotationExclusionStrategy.register();
GsonHolders.registerSerializer();
Logger.setMinimumLevel(FabricLoader.getInstance().isDevelopmentEnvironment() ? Level.TRACE : Level.INFO);
}
@Override
@ -27,7 +26,7 @@ public class LibJf implements PreLaunchEntrypoint {
public static void setup() {
if (!setup) {
setup = true;
Logger.registerFactory(SLF4JLogger::new);
HotswapLoggerFinder.updateAllStrategies((name, module, level) -> new SLF4JPlatformLogger(LoggerFactory.getLogger(name)));
}
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.libjf.log;
import io.gitlab.jfronny.commons.logger.HotswapLoggerFinder;
import io.gitlab.jfronny.commons.logger.LeveledLoggerFinder;
import io.gitlab.jfronny.commons.logger.SystemLoggerPlus;
import org.jetbrains.annotations.Nullable;
public class EarlyLoggerSetup extends LeveledLoggerFinder {
static {
HotswapLoggerFinder.updateAllStrategies((name, module, level) -> new LoaderPlatformLogger(name));
}
private final LeveledLoggerFinder delegate = new HotswapLoggerFinder();
@Override
public SystemLoggerPlus getLogger(String name, Module module, @Nullable System.Logger.Level level) {
return delegate.getLogger(name, module, level);
}
}

View File

@ -0,0 +1,57 @@
package io.gitlab.jfronny.libjf.log;
import io.gitlab.jfronny.commons.logger.CompactLogger;
import net.fabricmc.loader.impl.util.log.Log;
import net.fabricmc.loader.impl.util.log.LogCategory;
import net.fabricmc.loader.impl.util.log.LogLevel;
public class LoaderPlatformLogger implements CompactLogger {
private final LogCategory category;
public LoaderPlatformLogger(String context, String... names) {
this.category = LogCategory.createCustom(context, names);
}
@Override
public String getName() {
return category.name;
}
@Override
public Level getLevel() {
for (Level value : Level.values()) {
if (value == Level.ALL || value == Level.OFF) continue;
if (isLoggable(value)) return value;
}
return Level.INFO; // should not happen, but if it does, INFO is a reasonable default
}
@Override
public void log(Level level, String message) {
Log.log(jplLevelToFabricLevel(level), category, message);
}
@Override
public void log(Level level, String message, Throwable throwable) {
Log.log(jplLevelToFabricLevel(level), category, message, throwable);
}
@Override
public boolean isLoggable(Level level) {
if (level == Level.ALL) return true;
if (level == Level.OFF) return false;
return Log.shouldLog(jplLevelToFabricLevel(level), category);
}
private LogLevel jplLevelToFabricLevel(Level jplLevel) {
return switch (jplLevel) {
case TRACE -> LogLevel.TRACE;
case DEBUG -> LogLevel.DEBUG;
case INFO -> LogLevel.INFO;
case WARNING -> LogLevel.WARN;
case ERROR -> LogLevel.ERROR;
// should not happen, but if it does, INFO is a reasonable default
default -> LogLevel.INFO;
};
}
}

View File

@ -0,0 +1,116 @@
package io.gitlab.jfronny.libjf.log;
import io.gitlab.jfronny.commons.StringFormatter;
import io.gitlab.jfronny.commons.logger.CompactLogger;
import org.slf4j.Logger;
import org.slf4j.spi.CallerBoundaryAware;
import org.slf4j.spi.LoggingEventBuilder;
import java.text.MessageFormat;
import java.util.Objects;
import java.util.ResourceBundle;
/**
* A {@link System.Logger} implementation that delegates to SLF4J.
* Adapted from slf4j-jdk-platform-logging for use in LibJF.
*
* @author Ceki Gülcü
* @author JFronny
*/
public class SLF4JPlatformLogger implements CompactLogger {
private static final String PRESUMED_CALLER_BOUNDARY = System.Logger.class.getName();
private final Logger slf4jLogger;
public SLF4JPlatformLogger(Logger logger) {
slf4jLogger = Objects.requireNonNull(logger);
}
@Override
public String getName() {
return slf4jLogger.getName();
}
@Override
public Level getLevel() {
if (slf4jLogger.isTraceEnabled()) return Level.TRACE;
else if (slf4jLogger.isDebugEnabled()) return Level.DEBUG;
else if (slf4jLogger.isInfoEnabled()) return Level.INFO;
else if (slf4jLogger.isWarnEnabled()) return Level.WARNING;
else if (slf4jLogger.isErrorEnabled()) return Level.ERROR;
else return Level.INFO; // should not happen, but if it does, INFO is a reasonable default
}
@Override
public boolean isLoggable(Level level) {
if (level == Level.ALL) return true;
if (level == Level.OFF) return false;
return slf4jLogger.isEnabledForLevel(jplLevelToSLF4JLevel(level));
}
private org.slf4j.event.Level jplLevelToSLF4JLevel(Level jplLevel) {
return switch (jplLevel) {
case TRACE -> org.slf4j.event.Level.TRACE;
case DEBUG -> org.slf4j.event.Level.DEBUG;
case INFO -> org.slf4j.event.Level.INFO;
case WARNING -> org.slf4j.event.Level.WARN;
case ERROR -> org.slf4j.event.Level.ERROR;
// should not happen, but if it does, INFO is a reasonable default
default -> org.slf4j.event.Level.INFO;
};
}
@Override
public void log(Level level, String message) {
log(level, null, message, null, (Object[]) null);
}
@Override
public void log(Level level, String message, Throwable throwable) {
log(level, null, message, throwable, (Object[]) null);
}
@Override
public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {
log(level, bundle, msg, thrown, (Object[]) null);
}
@Override
public void log(Level level, ResourceBundle bundle, String format, Object... params) {
log(level, bundle, format, null, params);
}
private void log(Level jplLevel, ResourceBundle bundle, String msg, Throwable thrown, Object... params) {
if (jplLevel == Level.OFF) return;
if (jplLevel == Level.ALL) {
performLog(org.slf4j.event.Level.TRACE, bundle, msg, thrown, params);
return;
}
org.slf4j.event.Level slf4jLevel = jplLevelToSLF4JLevel(jplLevel);
if (slf4jLogger.isEnabledForLevel(slf4jLevel)) {
performLog(slf4jLevel, bundle, msg, thrown, params);
}
}
private void performLog(org.slf4j.event.Level slf4jLevel, ResourceBundle bundle, String msg, Throwable thrown, Object... params) {
String message = CompactLogger.getResourceStringOrMessage(bundle, msg);
LoggingEventBuilder leb = slf4jLogger.makeLoggingEventBuilder(slf4jLevel);
if (thrown != null) {
leb = leb.setCause(thrown);
}
if (params != null && params.length > 0) {
// add the arguments to the logging event for possible processing by the backend
String[] strings = new String[params.length];
for (int i = 0; i < params.length; i++) {
leb = leb.addArgument(params[i]);
strings[i] = StringFormatter.toString(params[i]);
}
// The JDK uses a different formatting convention. We must invoke it now.
message = new MessageFormat(message).format(strings);
}
if (leb instanceof CallerBoundaryAware cba) {
cba.setCallerBoundary(PRESUMED_CALLER_BOUNDARY);
}
leb.log(message);
}
}

View File

@ -0,0 +1 @@
io.gitlab.jfronny.libjf.log.EarlyLoggerSetup

View File

@ -9,8 +9,7 @@ base {
}
dependencies {
val fabricVersion: String by rootProject.extra
api(devProject(":libjf-base"))
api(devProject(":libjf-config-core-v2"))
include(modImplementation(fabricApi.module("fabric-command-api-v2", fabricVersion))!!)
include(modImplementation("net.fabricmc.fabric-api:fabric-command-api-v2")!!)
}

View File

@ -14,16 +14,12 @@ repositories {
}
dependencies {
val commonsVersion: String by rootProject.extra
val gsonCompileVersion: String by rootProject.extra
val annotationsVersion: String by rootProject.extra
val javapoetVersion: String by rootProject.extra
implementation("io.gitlab.jfronny.gson:gson-compile-processor-core:$gsonCompileVersion")
implementation(libs.gson.compile.processor.core)
implementation(devProject(":libjf-config-core-v2"))
implementation("org.jetbrains:annotations:$annotationsVersion")
implementation("io.gitlab.jfronny:commons:$commonsVersion")
implementation("io.gitlab.jfronny:commons-serialize-gson:$commonsVersion")
implementation("com.squareup:javapoet:$javapoetVersion")
implementation(libs.annotations)
implementation(libs.commons)
implementation(libs.commons.serialize.gson)
implementation(libs.javapoet)
testAnnotationProcessor(sourceSets.main.get().output)
configurations.testAnnotationProcessor.get().extendsFrom(configurations.implementation.get())
}

View File

@ -9,7 +9,6 @@ base {
}
dependencies {
val modmenuVersion: String by rootProject.extra
api(devProject(":libjf-base"))
modCompileOnly("com.terraformersmc:modmenu:$modmenuVersion")
modCompileOnly(libs.modmenu)
}

View File

@ -1,6 +1,5 @@
package io.gitlab.jfronny.libjf.config.api.v2;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.impl.ConfigHolderImpl;
import java.nio.file.Path;
@ -15,7 +14,6 @@ public interface ConfigHolder {
* @return The config holder
*/
static ConfigHolder getInstance() {
LibJf.setup();
return ConfigHolderImpl.INSTANCE;
}

View File

@ -9,11 +9,9 @@ base {
}
dependencies {
val fabricVersion: String by rootProject.extra
val modmenuVersion: String by rootProject.extra
api(devProject(":libjf-base"))
api(devProject(":libjf-config-core-v2"))
modCompileOnly("com.terraformersmc:modmenu:$modmenuVersion")
include(modImplementation(fabricApi.module("fabric-networking-api-v1", fabricVersion))!!)
include(modImplementation(fabricApi.module("fabric-command-api-v2", fabricVersion))!!)
modCompileOnly(libs.modmenu)
include(modImplementation("net.fabricmc.fabric-api:fabric-networking-api-v1")!!)
include(modImplementation("net.fabricmc.fabric-api:fabric-command-api-v2")!!)
}

View File

@ -9,8 +9,7 @@ base {
}
dependencies {
val fabricVersion: String by rootProject.extra
api(devProject(":libjf-base"))
api(devProject(":libjf-config-core-v2"))
include(fabricApi.module("fabric-resource-loader-v0", fabricVersion))
include("net.fabricmc.fabric-api:fabric-resource-loader-v0")
}

View File

@ -9,8 +9,7 @@ base {
}
dependencies {
val fabricVersion: String by rootProject.extra
api(devProject(":libjf-base"))
api(devProject(":libjf-unsafe-v0"))
modApi(fabricApi.module("fabric-api-base", fabricVersion))
modApi("net.fabricmc.fabric-api:fabric-api-base")
}

View File

@ -9,7 +9,6 @@ base {
}
dependencies {
val fabricVersion: String by rootProject.extra
api(devProject(":libjf-base"))
include(fabricApi.module("fabric-resource-loader-v0", fabricVersion))
include("net.fabricmc.fabric-api:fabric-resource-loader-v0")
}

View File

@ -7,6 +7,5 @@ base {
}
dependencies {
val fabricVersion: String by rootProject.extra
implementation(fabricApi.module("fabric-api-base", fabricVersion))
modImplementation("net.fabricmc.fabric-api:fabric-api-base")
}

View File

@ -9,8 +9,7 @@ base {
}
dependencies {
val commonsVersion: String by rootProject.extra
api(devProject(":libjf-base"))
compileOnly("io.gitlab.jfronny:commons-unsafe:$commonsVersion") { isTransitive = false }
shadow("io.gitlab.jfronny:commons-unsafe:$commonsVersion") { isTransitive = false }
compileOnly(libs.commons.unsafe) { isTransitive = false }
shadow(libs.commons.unsafe) { isTransitive = false }
}

View File

@ -1,118 +0,0 @@
package io.gitlab.jfronny.libjf.unsafe;
import io.gitlab.jfronny.commons.logging.Logger;
import net.fabricmc.loader.impl.util.log.Log;
import net.fabricmc.loader.impl.util.log.LogCategory;
public class FLLogger implements Logger {
private final LogCategory category;
public FLLogger(String context, String... names) {
this.category = LogCategory.createCustom(context, names);
}
@Override
public String getName() {
return category.name;
}
@Override
public void trace(String msg) {
Log.trace(category, msg);
}
@Override
public void trace(String format, Object arg) {
Log.trace(category, format, arg);
}
@Override
public void trace(String format, Object... args) {
Log.trace(category, format, args);
}
@Override
public void trace(String msg, Throwable t) {
Log.trace(category, msg, t);
}
@Override
public void debug(String msg) {
Log.debug(category, msg);
}
@Override
public void debug(String format, Object arg) {
Log.debug(category, format, arg);
}
@Override
public void debug(String format, Object... args) {
Log.debug(category, format, args);
}
@Override
public void debug(String msg, Throwable t) {
Log.debug(category, msg, t);
}
@Override
public void info(String msg) {
Log.info(category, msg);
}
@Override
public void info(String format, Object arg) {
Log.info(category, format, arg);
}
@Override
public void info(String format, Object... args) {
Log.info(category, format, args);
}
@Override
public void info(String msg, Throwable t) {
Log.info(category, msg, t);
}
@Override
public void warn(String msg) {
Log.warn(category, msg);
}
@Override
public void warn(String format, Object arg) {
Log.warn(category, format, arg);
}
@Override
public void warn(String format, Object... args) {
Log.warn(category, format, args);
}
@Override
public void warn(String msg, Throwable t) {
Log.warn(category, msg, t);
}
@Override
public void error(String msg) {
Log.error(category, msg);
}
@Override
public void error(String format, Object arg) {
Log.error(category, format, arg);
}
@Override
public void error(String format, Object... args) {
Log.error(category, format, args);
}
@Override
public void error(String msg, Throwable t) {
Log.error(category, msg, t);
}
}

View File

@ -1,9 +1,6 @@
package io.gitlab.jfronny.libjf.unsafe;
import io.gitlab.jfronny.commons.logging.Level;
import io.gitlab.jfronny.commons.logging.Logger;
import io.gitlab.jfronny.libjf.LibJf;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.LanguageAdapter;
public class JfLanguageAdapter implements LanguageAdapter {
@ -11,8 +8,6 @@ public class JfLanguageAdapter implements LanguageAdapter {
public native <T> T create(net.fabricmc.loader.api.ModContainer mod, String value, Class<T> type);
static {
Logger.registerFactory(FLLogger::new); // Reset in LibJf entrypoint
Logger.setMinimumLevel(FabricLoader.getInstance().isDevelopmentEnvironment() ? Level.TRACE : Level.INFO);
LibJf.LOGGER.info("Starting unsafe init"); // Also ensures LibJF.<clinit> is called and Gson is initialized
DynamicEntry.execute("libjf:preEarly", UltraEarlyInit.class, s -> s.instance().init());
DynamicEntry.execute("libjf:early", UltraEarlyInit.class, s -> s.instance().init());

View File

@ -9,11 +9,10 @@ base {
}
dependencies {
val fabricVersion: String by rootProject.extra
api(devProject(":libjf-base"))
api(devProject(":libjf-config-core-v2"))
api(devProject(":libjf-mainhttp-v0"))
include(modImplementation(fabricApi.module("fabric-command-api-v2", fabricVersion))!!)
include(modImplementation("net.fabricmc.fabric-api:fabric-command-api-v2")!!)
annotationProcessor(project(":libjf-config-compiler-plugin-v2"))
}

View File

@ -1,11 +1,13 @@
pluginManagement {
repositories {
maven("https://maven.fabricmc.net/") // FabricMC
maven("https://maven.architectury.dev/") // Architectury
maven("https://files.minecraftforge.net/maven/") // Forge
maven("https://maven.frohnmeyer-wds.de/artifacts") // scripts
gradlePluginPortal()
}
plugins {
id("jfmod") version("1.5-SNAPSHOT")
id("jfmod") version("1.6-SNAPSHOT")
id("jfmod.module")
}
}