Fix up logging and log4j configuration (#4802)

This commit is contained in:
mezz 2018-03-17 18:41:16 -07:00 committed by GitHub
parent 5ace86da12
commit ae654edfc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 308 additions and 206 deletions

View File

@ -27,7 +27,7 @@ Identifying the Source of a Problem
You're most likely to get fast and valuable responses to your issues if you report them in the correct place. For this, you need to find the root cause of the problem.
The most important source for this information are the log files Forge creates for every run of the game. You can find them in the `logs` subdirectory of your Minecraft game directory. The most important log file is `fml-client-latest.log` for client instances (singleplayer or *connecting* to a server) and `fml-server-latest.log` for dedicated servers which contains all of Forge's and any mod's output.
The most important source for this information are the log files Forge creates for every run of the game. You can find them in the `logs` subdirectory of your Minecraft game directory. The most important log file is `latest.log` which contains all of Forge's and any mod's output for `info` of above. `debug.log` contains all the logs in `latest.log` plus the `debug` logs for more detailed debugging.
If you're faced by a crash, consult these logs files first. Near the end of the log should be a section labelled 'Minecraft Crash Report', and after it, one about `a detailed walkthrough of the error, ...`. In these sections, you'll see a bunch of lines that look like
@ -108,7 +108,7 @@ If you're certain that your issue went unnoticed up until now, you can get to ac
- **Mod Version:** Just like the Forge and Minecraft version, this is crucial for quickly telling where an issue might come from. *If you're reporting an issue caused by Forge that only occurs with a certain mod installed, include this mod here. No mod version is required if it's a pure Forge bug.*
- **Complete List of Mods:** In order to reliably analyze a bug, developers need the exact same context as you do when trying to find its cause. Hence, you should always include a *full list of mods with their corresponding version* in your report. Note that you should probably only include the ones you found by [isolating the issue](#isolating-an-issue).
- **Steps to Reproduce:** You should always include a list of steps required to provoke an issue to occur. Without it, developers can only take rough guesses at what might cause the bug. Try to reduce the amount of steps to a bare minimum, to make reproducing the issue easier. If you require a sophisticated setup to get even close to the issue, you might want to consider including your save file in your report.
- **Full Log:** This is probably the most important part of your bug report. You *always* have to include the full log (`fml-client-latest.log` or `fml-server-latest.log` from earlier), since it is the only way of telling what has caused an issue in code. *Do not* paste the full log as plain text in your report, but use a site like [Pastebin](https://pastebin.com) or [GitHub Gist](https://gist.github.com) instead and link to that from your report.
- **Full Log:** This is probably the most important part of your bug report. You *always* have to include the full log (`debug.log` from earlier), since it is the only way of telling what has caused an issue in code. *Do not* paste the full log as plain text in your report, but use [GitHub Gist](https://gist.github.com) instead and link to that from your report.
### Markdown Issue Template
GitHub and BitBucket allow you to use the Markdown format for writing your issues. Below you can find a simple template that you can copy and fill in with your data. `{variables}` are written in braces and are supposed to be replaced by you with the information the variable name indicates. Everything behind two slashes (`//`) has to be interpreted as a comment and should be removed. If you want to include any link, you have to write in the `[title](url)` form. For further information on Markdown, see [this cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).

View File

@ -44,6 +44,7 @@ import javax.vecmath.Vector2f;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector4f;
import net.minecraftforge.common.ForgeVersion;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
@ -63,7 +64,7 @@ import com.google.common.collect.Table;
public class B3DModel
{
static final Logger logger = LogManager.getLogger(B3DModel.class);
static final Logger logger = LogManager.getLogger(ForgeVersion.MOD_ID + ".B3DModel");
private static final boolean printLoadedModels = "true".equals(System.getProperty("b3dloader.printLoadedModels"));
private final List<Texture> textures;
private final List<Brush> brushes;

View File

@ -68,7 +68,7 @@ public class ForgeVersion
@SuppressWarnings("unused")
private static String target = null;
private static final Logger log = LogManager.getLogger("ForgeVersionCheck");
private static final Logger log = LogManager.getLogger(MOD_ID + ".VersionCheck");
public static int getMajorVersion()
{

View File

@ -61,7 +61,7 @@ public final class UsernameCache {
private static final File saveFile = new File( /* The minecraft dir */(File) FMLInjectionData.data()[6], "usernamecache.json");
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
private static final Logger log = LogManager.getLogger(UsernameCache.class);
private static final Logger log = LogManager.getLogger(ForgeVersion.MOD_ID + ".UsernameCache");
private UsernameCache() {}

View File

@ -1047,7 +1047,7 @@ public class Configuration
}
catch (IOException e)
{
FMLLog.log.error("Error while loading config.", e);
FMLLog.log.error("Error while loading config {}.", fileName, e);
}
finally
{
@ -1108,7 +1108,7 @@ public class Configuration
}
catch (IOException e)
{
FMLLog.log.error("Error while saving config.", e);
FMLLog.log.error("Error while saving config {}.", fileName, e);
}
}

View File

@ -992,7 +992,7 @@ public class FMLClientHandler implements IFMLSidedHandler
{
return;
}
Logger logger = LogManager.getLogger("TEXTURE ERRORS");
Logger logger = LogManager.getLogger("FML.TEXTURE_ERRORS");
logger.error(Strings.repeat("+=", 25));
logger.error("The following texture errors were found.");
Map<String,FallbackResourceManager> resManagers = ObfuscationReflectionHelper.getPrivateValue(SimpleReloadableResourceManager.class, (SimpleReloadableResourceManager)Minecraft.getMinecraft().getResourceManager(), "domainResourceManagers", "field_110548"+"_a");

View File

@ -25,6 +25,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import net.minecraftforge.fml.common.FMLLog;
import org.apache.logging.log4j.LogManager;
import javax.imageio.ImageIO;
@ -59,7 +60,7 @@ public class FMLFileResourcePack extends FileResourcePack implements FMLContaine
{
if ("pack.mcmeta".equals(resourceName))
{
LogManager.getLogger(container.getName()).debug("Mod {} is missing a pack.mcmeta file, substituting a dummy one", container.getName());
FMLLog.log.debug("Mod {} is missing a pack.mcmeta file, substituting a dummy one", container.getName());
return new ByteArrayInputStream(("{\n" +
" \"pack\": {\n"+
" \"description\": \"dummy FML pack for "+container.getName()+"\",\n"+

View File

@ -25,6 +25,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import net.minecraftforge.fml.common.FMLLog;
import org.apache.logging.log4j.LogManager;
import javax.imageio.ImageIO;
@ -64,7 +65,7 @@ public class FMLFolderResourcePack extends FolderResourcePack implements FMLCont
{
if ("pack.mcmeta".equals(resourceName))
{
LogManager.getLogger(container.getName()).debug("Mod {} is missing a pack.mcmeta file, substituting a dummy one", container.getName());
FMLLog.log.debug("Mod {} is missing a pack.mcmeta file, substituting a dummy one", container.getName());
return new ByteArrayInputStream(("{\n" +
" \"pack\": {\n"+
" \"description\": \"dummy FML pack for "+container.getName()+"\",\n"+

View File

@ -31,7 +31,7 @@ import java.io.File;
public class GuiErrorBase extends GuiErrorScreen
{
static final File minecraftDir = new File(Loader.instance().getConfigDir().getParent());
static final File clientLog = new File(minecraftDir, "logs/fml-client-latest.log");
static final File logFile = new File(minecraftDir, "logs/latest.log");
public GuiErrorBase()
{
super(null, null);
@ -48,7 +48,7 @@ public class GuiErrorBase extends GuiErrorScreen
super.initGui();
this.buttonList.clear();
this.buttonList.add(new GuiButton(10, 50, this.height - 38, this.width / 2 - 55, 20, translateOrDefault("fml.button.open.mods.folder", "Open Mods Folder")));
String openFileText = translateOrDefault("fml.button.open.file", "Open %s", clientLog.getName());
String openFileText = translateOrDefault("fml.button.open.file", "Open %s", logFile.getName());
this.buttonList.add(new GuiButton(11, this.width / 2 + 5, this.height - 38, this.width / 2 - 55, 20, openFileText));
}
@ -71,11 +71,11 @@ public class GuiErrorBase extends GuiErrorScreen
{
try
{
Desktop.getDesktop().open(clientLog);
Desktop.getDesktop().open(logFile);
}
catch (Exception e)
{
FMLLog.log.error("Problem opening log file {}", clientLog, e);
FMLLog.log.error("Problem opening log file {}", logFile, e);
}
}
}

View File

@ -61,7 +61,7 @@ public class GuiModsMissing extends GuiErrorBase
this.drawCenteredString(this.fontRenderer, String.format(TextFormatting.BOLD + "%s" + TextFormatting.RESET + " : %s", v.getLabel(), v.getRangeString()), this.width / 2, offset, 0xEEEEEE);
}
offset+=20;
String seeLogText = I18n.format("fml.messages.mod.missing.dependencies.see.log", GuiErrorBase.clientLog.getName());
String seeLogText = I18n.format("fml.messages.mod.missing.dependencies.see.log", GuiErrorBase.logFile.getName());
this.drawCenteredString(this.fontRenderer, seeLogText, this.width / 2, offset, 0xFFFFFF);
super.drawScreen(mouseX, mouseY, partialTicks);
}

View File

@ -44,7 +44,7 @@ public class GuiWrongMinecraft extends GuiErrorBase
offset+=15;
this.drawCenteredString(this.fontRenderer, I18n.format("fml.messages.mod.wrongminecraft.fix", wrongMC.mod.getName()),this.width/2, offset, 0xFFFFFF);
offset+=20;
this.drawCenteredString(this.fontRenderer, I18n.format("fml.messages.mod.missing.dependencies.see.log", GuiErrorBase.clientLog.getName()), this.width / 2, offset, 0xFFFFFF);
this.drawCenteredString(this.fontRenderer, I18n.format("fml.messages.mod.missing.dependencies.see.log", GuiErrorBase.logFile.getName()), this.width / 2, offset, 0xFFFFFF);
super.drawScreen(mouseX, mouseY, partialTicks);
}
}

View File

@ -51,6 +51,7 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
@ -60,6 +61,8 @@ import javax.annotation.Nullable;
*/
public final class FMLContainer extends DummyModContainer implements WorldAccessContainer
{
private static final Logger modTrackerLogger = LogManager.getLogger("FML.ModTracker");
public FMLContainer()
{
super(new ModMetadata());
@ -190,12 +193,12 @@ public final class FMLContainer extends DummyModContainer implements WorldAccess
ModContainer container = Loader.instance().getIndexedModList().get(modId);
if (container == null)
{
LogManager.getLogger("fml.ModTracker").error("This world was saved with mod {} which appears to be missing, things may not work well", modId);
modTrackerLogger.error("This world was saved with mod {} which appears to be missing, things may not work well", modId);
continue;
}
if (!modVersion.equals(container.getVersion()))
{
LogManager.getLogger("fml.ModTracker").info("This world was saved with mod {} version {} and it is now at version {}, things may not work well", modId, modVersion, container.getVersion());
modTrackerLogger.info("This world was saved with mod {} version {} and it is now at version {}, things may not work well", modId, modVersion, container.getVersion());
}
}
}

View File

@ -19,37 +19,21 @@
package net.minecraftforge.fml.common;
import java.util.Locale;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.relauncher.FMLLaunchHandler;
import net.minecraftforge.fml.relauncher.FMLRelaunchLog;
import net.minecraftforge.fml.relauncher.Side;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
/**
* FMLs logging class. <b>Internal use only, NOT FOR MOD LOGGING!</b> Mods use your own log, see {@link FMLPreInitializationEvent#getModLog()}.
* TODO 1.13 remove all the deprecated methods
*/
public class FMLLog
{
public static final Logger log;
static {
log = LogManager.getLogger("FML");
// Default side to client for test harness purposes
Side side = FMLLaunchHandler.side();
if (side == null) side = Side.CLIENT;
ThreadContext.put("side", side.name().toLowerCase(Locale.ENGLISH));
log.debug("Injecting tracing printstreams for STDOUT/STDERR.");
System.setOut(new TracingPrintStream(LogManager.getLogger("STDOUT"), System.out));
System.setErr(new TracingPrintStream(LogManager.getLogger("STDERR"), System.err));
}
public static final Logger log = LogManager.getLogger("FML");
public static void bigWarning(String format, Object... data)
{

View File

@ -58,8 +58,6 @@ import net.minecraftforge.fml.relauncher.Side;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@ -106,8 +104,6 @@ public class FMLModContainer implements ModContainer
private URL updateJSONUrl;
private int classVersion;
private final Logger modLog;
public FMLModContainer(String className, ModCandidate container, Map<String, Object> modDescriptor)
{
this.className = className;
@ -129,8 +125,6 @@ public class FMLModContainer implements ModContainer
FMLLog.log.trace("Using custom language adapter {} for {} (modid: {})", languageAdapterType, this.className, getModId());
}
sanityCheckModId();
modLog = LogManager.getLogger(getModId());
}
private void sanityCheckModId()
@ -217,15 +211,15 @@ public class FMLModContainer implements ModContainer
modMetadata.requiredMods = info.requirements;
modMetadata.dependencies = info.dependencies;
modMetadata.dependants = info.dependants;
modLog.trace("Parsed dependency info : Requirements: {} After:{} Before:{}", info.requirements, info.dependencies, info.dependants);
FMLLog.log.trace("Parsed dependency info for {}: Requirements: {} After:{} Before:{}", getModId(), info.requirements, info.dependencies, info.dependants);
}
else
{
modLog.trace("Using mcmod dependency info : {} {} {}", modMetadata.requiredMods, modMetadata.dependencies, modMetadata.dependants);
FMLLog.log.trace("Using mcmod dependency info for {}: {} {} {}", getModId(), modMetadata.requiredMods, modMetadata.dependencies, modMetadata.dependants);
}
if (Strings.isNullOrEmpty(modMetadata.name))
{
modLog.info("Mod {} is missing the required element 'name'. Substituting {}", getModId(), getModId());
FMLLog.log.info("Mod {} is missing the required element 'name'. Substituting {}", getModId(), getModId());
modMetadata.name = getModId();
}
internalVersion = (String)descriptor.get("version");
@ -235,18 +229,18 @@ public class FMLModContainer implements ModContainer
if (versionProps != null)
{
internalVersion = versionProps.getProperty(getModId() + ".version");
modLog.debug("Found version {} for mod {} in version.properties, using", internalVersion, getModId());
FMLLog.log.debug("Found version {} for mod {} in version.properties, using", internalVersion, getModId());
}
}
if (Strings.isNullOrEmpty(internalVersion) && !Strings.isNullOrEmpty(modMetadata.version))
{
modLog.warn("Mod {} is missing the required element 'version' and a version.properties file could not be found. Falling back to metadata version {}", getModId(), modMetadata.version);
FMLLog.log.warn("Mod {} is missing the required element 'version' and a version.properties file could not be found. Falling back to metadata version {}", getModId(), modMetadata.version);
internalVersion = modMetadata.version;
}
if (Strings.isNullOrEmpty(internalVersion))
{
modLog.warn("Mod {} is missing the required element 'version' and no fallback can be found. Substituting '1.0'.", getModId());
FMLLog.log.warn("Mod {} is missing the required element 'version' and no fallback can be found. Substituting '1.0'.", getModId());
modMetadata.version = internalVersion = "1.0";
}
@ -274,7 +268,7 @@ public class FMLModContainer implements ModContainer
}
catch (MalformedURLException e)
{
modLog.debug("Specified json URL invalid: {}", jsonURL);
FMLLog.log.debug("Specified json URL for mod '{}' is invalid: {}", getModId(), jsonURL);
}
}
}
@ -284,7 +278,7 @@ public class FMLModContainer implements ModContainer
{
try
{
modLog.debug("Attempting to load the file version.properties from {} to locate a version number for {}", getSource().getName(), getModId());
FMLLog.log.debug("Attempting to load the file version.properties from {} to locate a version number for mod {}", getSource().getName(), getModId());
Properties version = null;
if (getSource().isFile())
{
@ -321,7 +315,7 @@ public class FMLModContainer implements ModContainer
}
catch (IOException e)
{
modLog.trace("Failed to find a usable version.properties file");
FMLLog.log.trace("Failed to find a usable version.properties file for mod {}", getModId());
return null;
}
}
@ -373,7 +367,7 @@ public class FMLModContainer implements ModContainer
{
if (this.enabled)
{
modLog.debug("Enabling mod {}", getModId());
FMLLog.log.debug("Enabling mod {}", getModId());
this.eventBus = bus;
this.controller = controller;
eventBus.register(this);
@ -403,7 +397,7 @@ public class FMLModContainer implements ModContainer
}
else
{
modLog.error("The mod {} appears to have an invalid event annotation {}. This annotation can only apply to methods with recognized event arguments - it will not be called", getModId(), a.annotationType().getSimpleName());
FMLLog.log.error("The mod {} appears to have an invalid event annotation {}. This annotation can only apply to methods with recognized event arguments - it will not be called", getModId(), a.annotationType().getSimpleName());
}
}
else if (a.annotationType().equals(Mod.InstanceFactory.class))
@ -415,11 +409,11 @@ public class FMLModContainer implements ModContainer
}
else if (!(Modifier.isStatic(m.getModifiers()) && m.getParameterTypes().length == 0))
{
modLog.error("The InstanceFactory annotation can only apply to a static method, taking zero arguments - it will be ignored on {}({})", m.getName(), Arrays.asList(m.getParameterTypes()));
FMLLog.log.error("The InstanceFactory annotation can only apply to a static method, taking zero arguments - it will be ignored on {}({}) for mod {}", m.getName(), Arrays.asList(m.getParameterTypes()), getModId());
}
else if (factoryMethod != null)
{
modLog.error("The InstanceFactory annotation can only be used once, the application to {}({}) will be ignored", m.getName(), Arrays.asList(m.getParameterTypes()));
FMLLog.log.error("The InstanceFactory annotation can only be used once, the application to {}({}) will be ignored for mod {}", m.getName(), Arrays.asList(m.getParameterTypes()), getModId());
}
}
}
@ -486,7 +480,7 @@ public class FMLModContainer implements ModContainer
}
catch (ReflectiveOperationException e)
{
modLog.warn("Attempting to load @{} in class {} for {} and failing", annotationName, targets.getClassName(), mc.getModId(), e);
FMLLog.log.warn("Attempting to load @{} in class {} for {} and failing", annotationName, targets.getClassName(), mc.getModId(), e);
}
}
if (f != null)
@ -497,7 +491,7 @@ public class FMLModContainer implements ModContainer
target = modInstance;
if (!modInstance.getClass().equals(clz))
{
modLog.warn("Unable to inject @{} in non-static field {}.{} for {} as it is NOT the primary mod instance", annotationName, targets.getClassName(), targets.getObjectName(), mc.getModId());
FMLLog.log.warn("Unable to inject @{} in non-static field {}.{} for {} as it is NOT the primary mod instance", annotationName, targets.getClassName(), targets.getObjectName(), mc.getModId());
continue;
}
}
@ -538,7 +532,7 @@ public class FMLModContainer implements ModContainer
{
warnLevel = Level.TRACE;
}
modLog.log(warnLevel, "The mod {} is expecting signature {} for source {}, however there is no signature matching that description", getModId(), expectedFingerprint, source.getName());
FMLLog.log.log(warnLevel, "The mod {} is expecting signature {} for source {}, however there is no signature matching that description", getModId(), expectedFingerprint, source.getName());
}
else
{
@ -575,7 +569,7 @@ public class FMLModContainer implements ModContainer
}
Method factoryMethod = gatherAnnotations(clazz);
modInstance = getLanguageAdapter().getNewInstance(this, clazz, modClassLoader, factoryMethod);
NetworkRegistry.INSTANCE.register(this, clazz, (String)(descriptor.containsKey("acceptableRemoteVersions") ? descriptor.get("acceptableRemoteVersions") : null), event.getASMHarvestedData());
NetworkRegistry.INSTANCE.register(this, clazz, (String)(descriptor.getOrDefault("acceptableRemoteVersions", null)), event.getASMHarvestedData());
if (fingerprintNotPresent)
{
eventBus.post(new FMLFingerprintViolationEvent(source.isDirectory(), source, ImmutableSet.copyOf(this.sourceFingerprints), expectedFingerprint));

View File

@ -131,7 +131,7 @@ public class LoadController
}
else
{
LogManager.getLogger(mod.getModId()).warn("Mod {} has been disabled through configuration", mod.getModId());
FMLLog.log.warn("Mod {} has been disabled through configuration", mod.getModId());
modStates.put(mod.getModId(), ModState.UNLOADED);
modStates.put(mod.getModId(), ModState.DISABLED);
}
@ -266,7 +266,7 @@ public class LoadController
{
if (av.getLabel()!= null && requirements.contains(av.getLabel()) && modStates.containsEntry(av.getLabel(),ModState.ERRORED))
{
LogManager.getLogger(modId).error("Skipping event {} and marking errored mod {} since required dependency {} has errored", stateEvent.getEventType(), modId, av.getLabel());
FMLLog.log.error("Skipping event {} and marking errored mod {} since required dependency {} has errored", stateEvent.getEventType(), modId, av.getLabel());
modStates.put(modId, ModState.ERRORED);
return;
}
@ -274,9 +274,9 @@ public class LoadController
activeContainer = mc;
stateEvent.applyModContainer(mc);
ThreadContext.put("mod", modId);
LogManager.getLogger(modId).trace("Sending event {} to mod {}", stateEvent.getEventType(), modId);
FMLLog.log.trace("Sending event {} to mod {}", stateEvent.getEventType(), modId);
eventChannels.get(modId).post(stateEvent);
LogManager.getLogger(modId).trace("Sent event {} to mod {}", stateEvent.getEventType(), modId);
FMLLog.log.trace("Sent event {} to mod {}", stateEvent.getEventType(), modId);
ThreadContext.remove("mod");
activeContainer = null;
if (stateEvent instanceof FMLStateEvent)

View File

@ -29,6 +29,7 @@ import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import net.minecraftforge.fml.common.FMLLog;
import org.apache.commons.io.IOUtils;
import net.minecraft.launchwrapper.LaunchClassLoader;
@ -42,8 +43,6 @@ import net.minecraftforge.fml.relauncher.Side;
import com.google.common.io.ByteStreams;
import static net.minecraftforge.fml.common.FMLLog.log;
public class FMLSanityChecker implements IFMLCallHook
{
private static final String FMLFINGERPRINT = "51:0A:FB:4C:AF:A4:A0:F2:F5:CF:C5:0E:B4:CC:3C:30:24:4A:E3:8E".toLowerCase().replace(":", "");
@ -71,17 +70,17 @@ public class FMLSanityChecker implements IFMLCallHook
String fingerprint = CertificateHelper.getFingerprint(cert);
if (fingerprint.equals(FMLFINGERPRINT))
{
log.info("Found valid fingerprint for FML. Certificate fingerprint {}", fingerprint);
FMLLog.log.info("Found valid fingerprint for FML. Certificate fingerprint {}", fingerprint);
goodFML = true;
}
else if (fingerprint.equals(FORGEFINGERPRINT))
{
log.info("Found valid fingerprint for Minecraft Forge. Certificate fingerprint {}", fingerprint);
FMLLog.log.info("Found valid fingerprint for Minecraft Forge. Certificate fingerprint {}", fingerprint);
goodFML = true;
}
else
{
log.error("Found invalid fingerprint for FML: {}", fingerprint);
FMLLog.log.error("Found invalid fingerprint for FML: {}", fingerprint);
}
}
}
@ -133,7 +132,7 @@ public class FMLSanityChecker implements IFMLCallHook
String fingerprint = CertificateHelper.getFingerprint(cert);
if (fingerprint.equals(MCFINGERPRINT))
{
log.info("Found valid fingerprint for Minecraft. Certificate fingerprint {}", fingerprint);
FMLLog.log.info("Found valid fingerprint for Minecraft. Certificate fingerprint {}", fingerprint);
goodMC = true;
}
}
@ -141,7 +140,7 @@ public class FMLSanityChecker implements IFMLCallHook
}
catch (Throwable e)
{
log.error("A critical error occurred trying to read the minecraft jar file", e);
FMLLog.log.error("A critical error occurred trying to read the minecraft jar file", e);
}
finally
{
@ -154,11 +153,11 @@ public class FMLSanityChecker implements IFMLCallHook
}
if (!goodMC)
{
log.error("The minecraft jar {} appears to be corrupt! There has been CRITICAL TAMPERING WITH MINECRAFT, it is highly unlikely minecraft will work! STOP NOW, get a clean copy and try again!", codeSource.getLocation().getFile());
FMLLog.log.error("The minecraft jar {} appears to be corrupt! There has been CRITICAL TAMPERING WITH MINECRAFT, it is highly unlikely minecraft will work! STOP NOW, get a clean copy and try again!", codeSource.getLocation().getFile());
if (!Boolean.parseBoolean(System.getProperty("fml.ignoreInvalidMinecraftCertificates","false")))
{
log.error("For your safety, FML will not launch minecraft. You will need to fetch a clean version of the minecraft jar file");
log.error("Technical information: The class net.minecraft.client.ClientBrandRetriever should have been associated with the minecraft jar file, " +
FMLLog.log.error("For your safety, FML will not launch minecraft. You will need to fetch a clean version of the minecraft jar file");
FMLLog.log.error("Technical information: The class net.minecraft.client.ClientBrandRetriever should have been associated with the minecraft jar file, " +
"and should have returned us a valid, intact minecraft jar location. This did not work. Either you have modified the minecraft jar file (if so " +
"run the forge installer again), or you are using a base editing jar that is changing this class (and likely others too). If you REALLY " +
"want to run minecraft in this configuration, add the flag -Dfml.ignoreInvalidMinecraftCertificates=true to the 'JVM settings' in your launcher profile.");
@ -166,13 +165,13 @@ public class FMLSanityChecker implements IFMLCallHook
}
else
{
log.error("FML has been ordered to ignore the invalid or missing minecraft certificate. This is very likely to cause a problem!");
log.error("Technical information: ClientBrandRetriever was at {}, there were {} certificates for it", codeSource.getLocation(), certCount);
FMLLog.log.error("FML has been ordered to ignore the invalid or missing minecraft certificate. This is very likely to cause a problem!");
FMLLog.log.error("Technical information: ClientBrandRetriever was at {}, there were {} certificates for it", codeSource.getLocation(), certCount);
}
}
if (!goodFML)
{
log.error("FML appears to be missing any signature data. This is not a good thing");
FMLLog.log.error("FML appears to be missing any signature data. This is not a good thing");
}
return null;
}

View File

@ -151,11 +151,9 @@ public class FMLPreInitializationEvent extends FMLStateEvent
*/
public Logger getModLog()
{
Logger log = LogManager.getLogger(modContainer.getModId());
return log;
return LogManager.getLogger(modContainer.getModId());
}
/**
* Retrieve the FML signing certificates, if any. Validate these against the
* published FML certificates in your mod, if you wish.

View File

@ -37,7 +37,7 @@ public class FMLServerTweaker extends FMLTweaker {
if (System.getProperty("log4j.configurationFile") == null)
{
System.setProperty("log4j.configurationFile", "log4j2_server.xml");
System.setProperty("log4j.configurationFile", "log4j2.xml");
((LoggerContext) LogManager.getContext(false)).reconfigure();
}
}

View File

@ -129,7 +129,7 @@ public class FMLTweaker implements ITweaker {
}
catch (URISyntaxException e)
{
LogManager.getLogger("FMLTWEAK").log(Level.ERROR, "Missing URI information for FML tweak");
LogManager.getLogger("FML.TWEAK").error("Missing URI information for FML tweak");
throw new RuntimeException(e);
}
}

View File

@ -48,7 +48,7 @@ public class Yggdrasil
}
catch (AuthenticationException e)
{
LogManager.getLogger("FMLTWEAK").error("-- Login failed! {}", e.getMessage(), e);
LogManager.getLogger("FML.TWEAK").error("-- Login failed!", e);
throw new RuntimeException(e); // don't set other variables
}

View File

@ -31,16 +31,13 @@ import java.util.jar.JarFile;
import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import net.minecraftforge.fml.repackage.com.nothome.delta.Delta;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import java.util.logging.Logger;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
@ -56,7 +53,8 @@ public class GenDiffSet {
String outputDir = args[3]; //Path to place generated .binpatch
String killTarget = args[4]; //"true" if we should destroy the target file if it generated a successful .binpatch
LogManager.getLogger("GENDIFF").log(Level.INFO, String.format("Creating patches at %s for %s from %s", outputDir, sourceJar, targetDir));
Logger logger = LogManager.getLogger("FML.GENDIFF");
logger.info("Creating patches at {} for {} from {}", outputDir, sourceJar, targetDir);
Delta delta = new Delta();
FMLDeobfuscatingRemapper remapper = FMLDeobfuscatingRemapper.INSTANCE;
remapper.setupLoadOnly(deobfData, false);
@ -109,11 +107,11 @@ public class GenDiffSet {
File target = new File(outputDir, targetClassName+".binpatch");
target.getParentFile().mkdirs();
Files.write(diffOut.toByteArray(), target);
Logger.getLogger("GENDIFF").info(String.format("Wrote patch for %s (%s) at %s",name, targetClassName, target.getAbsolutePath()));
logger.info("Wrote patch for {} ({}) at {}", name, targetClassName, target.getAbsolutePath());
if (kill)
{
targetFile.delete();
Logger.getLogger("GENDIFF").info(String.format(" Deleted target: %s", targetFile.toString()));
logger.info(" Deleted target: {}", targetFile);
}
}
}

View File

@ -28,10 +28,9 @@ import java.util.Set;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.LoaderException;
import net.minecraftforge.fml.relauncher.Side;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public final class DependencyParser
{
@ -42,7 +41,6 @@ public final class DependencyParser
public final List<ArtifactVersion> dependants = new ArrayList<>();
}
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final ImmutableList<String> DEPENDENCY_INSTRUCTIONS = ImmutableList.of("client", "server", "required", "before", "after");
private static final Splitter DEPENDENCY_INSTRUCTIONS_SPLITTER = Splitter.on("-").omitEmptyStrings().trimResults();
private static final Splitter DEPENDENCY_PART_SPLITTER = Splitter.on(":").omitEmptyStrings().trimResults();
@ -189,15 +187,15 @@ public final class DependencyParser
{
if (Strings.isNullOrEmpty(depModId))
{
LOGGER.error(new DependencyParserException(modId, dep, "The modId is null or empty").getMessage());
FMLLog.log.error(new DependencyParserException(modId, dep, "The modId is null or empty").getMessage());
}
else if (depModId.length() > 64)
{
LOGGER.error(new DependencyParserException(modId, dep, String.format("The modId '%s' is longer than the maximum of 64 characters.", depModId)).getMessage());
FMLLog.log.error(new DependencyParserException(modId, dep, String.format("The modId '%s' is longer than the maximum of 64 characters.", depModId)).getMessage());
}
else if (!depModId.equals(depModId.toLowerCase(Locale.ENGLISH)))
{
LOGGER.error(new DependencyParserException(modId, dep, String.format("The modId '%s' must be all lowercase.", depModId)).getMessage());
FMLLog.log.error(new DependencyParserException(modId, dep, String.format("The modId '%s' must be all lowercase.", depModId)).getMessage());
}
}

View File

@ -23,7 +23,9 @@ import java.io.File;
import net.minecraft.launchwrapper.LaunchClassLoader;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.TracingPrintStream;
import net.minecraftforge.fml.common.launcher.FMLTweaker;
import org.apache.logging.log4j.LogManager;
public class FMLLaunchHandler
{
@ -79,12 +81,12 @@ public class FMLLaunchHandler
{
side = Side.SERVER;
setupHome();
}
private void setupHome()
{
FMLInjectionData.build(minecraftHome, classLoader);
redirectStdOutputToLog();
FMLLog.log.info("Forge Mod Loader version {}.{}.{}.{} for Minecraft {} loading", FMLInjectionData.major, FMLInjectionData.minor,
FMLInjectionData.rev, FMLInjectionData.build, FMLInjectionData.mccversion);
FMLLog.log.info("Java is {}, version {}, running on {}:{}:{}, installed at {}", System.getProperty("java.vm.name"), System.getProperty("java.version"), System.getProperty("os.name"), System.getProperty("os.arch"), System.getProperty("os.version"), System.getProperty("java.home"));
@ -105,6 +107,13 @@ public class FMLLaunchHandler
}
}
private void redirectStdOutputToLog()
{
FMLLog.log.debug("Injecting tracing printstreams for STDOUT/STDERR.");
System.setOut(new TracingPrintStream(LogManager.getLogger("STDOUT"), System.out));
System.setErr(new TracingPrintStream(LogManager.getLogger("STDERR"), System.err));
}
public static Side side()
{
return side;

View File

@ -28,6 +28,7 @@ import org.apache.logging.log4j.Logger;
/**
* Legacy FML logging class. Mods use {@link FMLPreInitializationEvent#getModLog()} instead, for Forge internal use use FMLLog.
* TODO 1.13 remove this class
*/
@Deprecated
public class FMLRelaunchLog {

View File

@ -36,6 +36,7 @@ import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.core.util.Booleans;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.fusesource.jansi.AnsiConsole;
@ -47,6 +48,13 @@ import jline.console.ConsoleReader;
import javax.annotation.Nullable;
/**
* TODO 1.13 remove this class
* @deprecated use the version in the log4j sub-package: {@link net.minecraftforge.server.console.log4j.TerminalConsoleAppender}
* This is being moved into its own package so that the log configuration doesn't load this whole package,
* which has references to Minecraft in it that can load lots of extra classes.
*/
@Deprecated
@Plugin(name = "TerminalConsole", category = "Core", elementType = "appender", printObject = true)
public class TerminalConsoleAppender extends AbstractAppender
{
@ -67,7 +75,7 @@ public class TerminalConsoleAppender extends AbstractAppender
public static void setFormatter(Function<String, String> format)
{
formatter = format != null ? format : Functions.<String> identity();
formatter = format != null ? format : Functions.identity();
}
protected TerminalConsoleAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions)
@ -78,7 +86,7 @@ public class TerminalConsoleAppender extends AbstractAppender
@PluginFactory
@Nullable
public static TerminalConsoleAppender createAppender(@PluginAttribute("name") String name, @PluginElement("Filters") Filter filter,
@PluginElement("Layout") Layout<? extends Serializable> layout, @PluginAttribute("ignoreExceptions") String ignore)
@PluginElement("Layout") Layout<? extends Serializable> layout, @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) String ignore)
{
if (name == null)
@ -91,7 +99,7 @@ public class TerminalConsoleAppender extends AbstractAppender
layout = PatternLayout.newBuilder().build();
}
boolean ignoreExceptions = Boolean.parseBoolean(ignore);
boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
// This is handled by jline
System.setProperty("log4j.skipJansi", "true");

View File

@ -24,8 +24,6 @@ import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.function.Function;
import jline.console.ConsoleReader;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.util.text.TextFormatting;

View File

@ -0,0 +1,187 @@
/*
* Minecraft Forge
* Copyright (c) 2016.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.server.console.log4j;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Serializable;
import java.io.Writer;
import java.util.function.Function;
import static jline.TerminalFactory.OFF;
import static jline.console.ConsoleReader.RESET_LINE;
import com.google.common.base.Functions;
import jline.TerminalFactory;
import jline.console.ConsoleReader;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.core.util.Booleans;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.fusesource.jansi.AnsiConsole;
@Plugin(name = "TerminalConsole", category = "Core", elementType = "appender", printObject = true)
public class TerminalConsoleAppender extends AbstractAppender
{
private static final boolean ENABLE_JLINE = PropertiesUtil.getProperties().getBooleanProperty("jline.enable", true);
private static final PrintStream out = System.out;
private static boolean initialized;
private static ConsoleReader reader;
public static ConsoleReader getReader()
{
return reader;
}
private static Function<String, String> formatter = Functions.identity();
public static void setFormatter(Function<String, String> format)
{
formatter = format != null ? format : Functions.identity();
}
protected TerminalConsoleAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions)
{
super(name, filter, layout, ignoreExceptions);
}
@PluginFactory
@Nullable
public static TerminalConsoleAppender createAppender(@PluginAttribute("name") String name, @PluginElement("Filters") Filter filter,
@PluginElement("Layout") Layout<? extends Serializable> layout, @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) String ignore)
{
if (name == null)
{
LOGGER.error("No name provided for TerminalConsoleAppender");
return null;
}
if (layout == null)
{
layout = PatternLayout.newBuilder().build();
}
boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
// This is handled by jline
System.setProperty("log4j.skipJansi", "true");
return new TerminalConsoleAppender(name, filter, layout, ignoreExceptions);
}
@Override
public void start()
{
// Initialize the reader if that hasn't happened yet
if (!initialized && reader == null)
{
initialized = true;
if (ENABLE_JLINE)
{
final boolean hasConsole = System.console() != null;
if (hasConsole)
{
try
{
AnsiConsole.systemInstall();
reader = new ConsoleReader();
reader.setExpandEvents(false);
}
catch (Exception e)
{
LOGGER.warn("Failed to initialize terminal. Falling back to default.", e);
}
}
if (reader == null)
{
// Eclipse doesn't support colors and characters like \r so enabling jline2 on it will
// just cause a lot of issues with empty lines and weird characters.
// Enable jline2 only on IntelliJ IDEA to prevent that.
// Also see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=76936
if (hasConsole || System.getProperty("java.class.path").contains("idea_rt.jar"))
{
// Disable advanced jline features
TerminalFactory.configure(OFF);
TerminalFactory.reset();
try
{
reader = new ConsoleReader();
reader.setExpandEvents(false);
}
catch (Exception e)
{
LOGGER.warn("Failed to initialize fallback terminal. Falling back to standard output console.", e);
}
}
else
{
LOGGER.warn("Disabling terminal, you're running in an unsupported environment.");
}
}
}
}
super.start();
}
@Override
public void append(LogEvent event)
{
if (reader != null)
{
try
{
Writer out = reader.getOutput();
out.write(RESET_LINE);
out.write(formatEvent(event));
reader.drawLine();
reader.flush();
}
catch (IOException ignored)
{
}
}
else
{
out.print(formatEvent(event));
}
}
protected String formatEvent(LogEvent event)
{
return formatter.apply(getLayout().toSerializable(event).toString());
}
}

View File

@ -1,59 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" packages="com.mojang.util">
<Configuration status="warn" packages="com.mojang.util,net.minecraftforge.server.console.log4j">
<Appenders>
<Console name="FmlSysOut" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger]: %msg%n" />
</Console>
<Console name="SysOut" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
</Console>
<TerminalConsole name="Console">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger]: %msg%n"/>
</TerminalConsole>
<!-- Keep a console appender open so log4j2 doesn't close our main out stream if we redirect System.out to the logger -->
<Console name="SysOut" target="SYSTEM_OUT"/>
<Queue name="ServerGuiConsole" ignoreExceptions="true">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger]: %msg%n" />
</Queue>
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger]: %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy />
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy/>
<OnStartupTriggeringPolicy/>
</Policies>
</RollingRandomAccessFile>
<Routing name="FmlFile">
<Routes pattern="$${ctx:side}">
<Route>
<RollingRandomAccessFile name="FmlFile" fileName="logs/fml-${ctx:side}-latest.log" filePattern="logs/fml-${ctx:side}-%i.log">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger/%X{mod}]: %msg%n" />
<DefaultRolloverStrategy max="3" fileIndex="max" />
<Policies>
<OnStartupTriggeringPolicy />
</Policies>
</RollingRandomAccessFile>
</Route>
<Route key="$${ctx:side}">
<RandomAccessFile name="FmlFile" fileName="logs/fml-junk-earlystartup.log" >
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger]: %msg%n" />
</RandomAccessFile>
</Route>
</Routes>
</Routing>
<RollingRandomAccessFile name="DebugFile" fileName="logs/debug.log" filePattern="logs/debug-%i.log.gz">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger]: %msg%n"/>
<Policies>
<OnStartupTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="200MB"/>
</Policies>
<DefaultRolloverStrategy max="5" fileIndex="min"/>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Logger level="info" name="com.mojang" additivity="false">
<AppenderRef ref="SysOut" level="INFO" />
<AppenderRef ref="File" />
<AppenderRef ref="ServerGuiConsole" level="INFO" />
</Logger>
<Logger level="info" name="net.minecraft" additivity="false">
<filters>
<MarkerFilter marker="NETWORK_PACKETS" onMatch="DENY" onMismatch="NEUTRAL" />
</filters>
<AppenderRef ref="SysOut" level="INFO" />
<AppenderRef ref="File" />
<AppenderRef ref="ServerGuiConsole" level="INFO" />
</Logger>
<!-- make sure mojang's logging is set to 'info' so that their LOGGER.isDebugEnabled() behavior isn't active -->
<Logger level="info" name="com.mojang"/>
<Logger level="info" name="net.minecraft"/>
<Root level="all">
<AppenderRef ref="FmlSysOut" level="INFO" />
<AppenderRef ref="ServerGuiConsole" level="INFO" />
<AppenderRef ref="FmlFile"/>
<filters>
<MarkerFilter marker="NETWORK_PACKETS" onMatch="DENY" onMismatch="NEUTRAL"/>
</filters>
<AppenderRef ref="Console" level="info"/>
<AppenderRef ref="File" level="info"/>
<AppenderRef ref="ServerGuiConsole" level="info"/>
<AppenderRef ref="DebugFile"/>
</Root>
</Loggers>
</Configuration>

View File

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" packages="com.mojang.util,net.minecraftforge.server.console">
<Appenders>
<TerminalConsole name="FmlConsole">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger]: %msg%n" />
</TerminalConsole>
<TerminalConsole name="Console">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
</TerminalConsole>
<!-- Keep a console appender open so log4j2 doesn't close our main out stream if we redirect System.out to the logger -->
<Console name="SysOut" target="SYSTEM_OUT"/>
<Queue name="ServerGuiConsole" ignoreExceptions="true">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger]: %replace{%msg}{(?i)\u00A7[0-9A-FK-OR]}{}%n" />
</Queue>
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %replace{%msg}{(?i)\u00A7[0-9A-FK-OR]}{}%n" />
<Policies>
<TimeBasedTriggeringPolicy />
<OnStartupTriggeringPolicy />
</Policies>
</RollingRandomAccessFile>
<Routing name="FmlFile">
<Routes pattern="$${ctx:side}">
<Route>
<RollingRandomAccessFile name="FmlFile" fileName="logs/fml-${ctx:side}-latest.log" filePattern="logs/fml-${ctx:side}-%i.log">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger/%X{mod}]: %replace{%msg}{(?i)\u00A7[0-9A-FK-OR]}{}%n" />
<DefaultRolloverStrategy max="3" fileIndex="max" />
<Policies>
<OnStartupTriggeringPolicy />
</Policies>
</RollingRandomAccessFile>
</Route>
<Route key="$${ctx:side}">
<RandomAccessFile name="FmlFile" fileName="logs/fml-junk-earlystartup.log" >
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level] [%logger]: %replace{%msg}{(?i)\u00A7[0-9A-FK-OR]}{}%n" />
</RandomAccessFile>
</Route>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Logger level="info" name="com.mojang" additivity="false">
<AppenderRef ref="Console" level="INFO" />
<AppenderRef ref="File" />
<AppenderRef ref="ServerGuiConsole" level="INFO" />
</Logger>
<Logger level="info" name="net.minecraft" additivity="false">
<filters>
<MarkerFilter marker="NETWORK_PACKETS" onMatch="DENY" onMismatch="NEUTRAL" />
</filters>
<AppenderRef ref="Console" level="INFO" />
<AppenderRef ref="File" />
<AppenderRef ref="ServerGuiConsole" level="INFO" />
</Logger>
<Root level="all">
<AppenderRef ref="FmlConsole" level="INFO" />
<AppenderRef ref="ServerGuiConsole" level="INFO" />
<AppenderRef ref="FmlFile"/>
</Root>
</Loggers>
</Configuration>