← Назад к ресурсам

Log Filter

A lightweight log filtering mod designed to reduce spam in the console and log files, allowing developers and players to focus on critical errors and save disk space.

Modrinth

Описание

# Log Filter A lightweight log filtering mod designed to reduce spam in the console and log files, allowing developers and players to focus on critical errors and save disk space. ## Features - **Regex Filtering**: Supports powerful regex matching to precisely filter specific log content. - **Exact Match Filtering**: Can precisely filter out specified entire lines of text. - **Filter by Logger**: Supports filtering all logs from a mod or class name (Logger Name). - **Filter by Log Level**: One-click blocking of low-level logs like `TRACE` or `DEBUG`. > Block `INFO` logs? Of course! This way you will only see errors and warnings, suitable for debugging. - **Whitelist Mode**: Set exclusion rules to ensure important logs (like critical errors) are not accidentally deleted. - **Efficient Caching**: Built-in deduplication cache mechanism to avoid processing the same logs repeatedly. ## Installation 1. Download the mod's JAR file. 2. Put the JAR file into the `mods` folder in your Minecraft installation directory. 3. Launch the game once. The mod will automatically generate a default configuration file. 4. Modify the configuration file as needed, then **restart the game** for the configuration to take effect. > Or manually create a `logfilter-common.toml` file, modify the configuration as needed, and then launch the game. ## Configuration Brief The configuration file is located at: `config/logfilter-common.toml` Default configuration: ```toml [General] #Enable or disable log filtering enableFilter = true #Enable debug mode to see which logs are being filtered debugMode = false #Maximum size of filtered log cache (for duplicate detection) #Range: 100 ~ 10000 maxCacheSize = 1000 [FilterRules] #Regex patterns to filter log messages filterRules = [] #Exact message strings to filter (case-sensitive) exactMatches = [] #Logger names to completely filter (e.g., 'net.minecraft.server.MinecraftServer') loggerNames = [] #Log levels to filter: TRACE, DEBUG, INFO, WARN, ERROR, FATAL logLevels = ["TRACE", "DEBUG"] #Regex patterns that will EXCLUDE logs from filtering (whitelist) excludePatterns = [] ``` ### General (General Settings) | Option | Default | Description | | :--- | :--- | :--- | | `enableFilter` | `true` | Whether to enable the log filtering function. | | `debugMode` | `false` | Enable debug mode to print filtered logs to the console, convenient for testing rules. | | `maxCacheSize` | `1000` | The cache size for filtered logs, used for deduplication. | ### FilterRules (Filtering Rules) #### 1. `filterRules` (Regex) Use regex to match logs to be filtered. ```toml filterRules = [ ".*Exception.*", # Filter out all logs containing "Exception" ".*stack trace.*", # Filter out stack traces ".*Could not pass event.*"# Filter out specific event errors ] ``` #### 2. `exactMatches` (Exact Match) Logs are filtered only when their content is **exactly identical** (case-sensitive). ```toml exactMatches = [ "This message will be completely filtered out" ] ``` #### 3. `loggerNames` (Logger Names) Filter based on the source of the log (class name or mod package name). Supports hierarchical filtering. ```toml loggerNames = [ "net.minecraft.server.MinecraftServer", # Filter out logs from the main server "com.some.noisy.mod" # Filter out all logs from a noisy mod ] ``` #### 4. `logLevels` (Log Levels) Filter based on log level. Available values: `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`. ```toml logLevels = [ "TRACE", "DEBUG" ] ``` #### 5. `excludePatterns` (Whitelist/Exclusion Rules) **Very Important**. Logs matching rules here will **not** be filtered, even if other rules match them. Used to retain critical errors. ```toml excludePatterns = [ ".*CRITICAL ERROR.*", # Even if it matches Exception, if it is a CRITICAL ERROR, keep it ".*IMPORTANT.*" ] ``` ## 🔨 Build If you want to compile this mod yourself: ```bash ./gradlew build ``` The compiled JAR file is located in the `build/libs/` directory. --- ## Deep Dive ### Part 1: How it works at the mod code level The core idea of this mod is **interception**. It "hijacks" the data before Minecraft's log output reaches the console or files, deciding whether to let it pass or discard it. #### 1. Log Framework Basics: Log4j 2 Minecraft 1.20.1 uses the **Log4j 2** logging framework. * **Log Flow**: Game code generates log events (`LogEvent`) -> Passes to Log4j's `LoggerContext` -> Passes to `Appender` (e.g., console appender, file writer) -> Finally displayed on the screen. * **Filter Mechanism**: Log4j allows mounting "filters (`Filter`)" on Loggers or Appenders. #### 2. Code Execution Flow Our mod performs the following operations via `LogFilterManager.java` when the game starts (`FMLCommonSetupEvent`): 1. **Get Context**: ```java LoggerContext loggerContext = LoggerContext.getContext(false); ``` We obtained Minecraft's current log environment context. 3. **Get Root Configuration**: ```java Configuration configuration = loggerContext.getConfiguration(); LoggerConfig rootLoggerConfig = configuration.getRootLogger(); ``` We got the configuration of the "Root Logger". Since almost all logs eventually flow to the Root Logger, mounting a filter here can capture global logs. 5. **Register Custom Filter**: ```java log4jFilter = new FilteringLogFilter(); // Our custom filter class log4jFilter.start(); rootLoggerConfig.addFilter(log4jFilter); ``` We inserted our custom `FilteringLogFilter` at the very front of the log processing chain. 7. **Interception and Decision Making (`FilteringLogFilter.filter` method):** Whenever Minecraft attempts to output a log line, Log4j invokes our `filter(LogEvent event)` method. To prevent game stuttering caused by log filtering, we adopt a "fail-fast" design, with the following logic priority: * **Step A: Extract Key Information.** Directly extract key details such as the Logger name and level from the Log4j `LogEvent`. * **Step B: Quick Check (Level & Logger).** Prioritize checking the log level (`logLevels`) and Logger name (`loggerNames`). This is an extremely low-overhead operation. If a match is found, the log is discarded immediately, **completely skipping the expensive message formatting and regex matching that follows**, significantly reducing main thread overhead. * **Step C: Message Formatting.** Only when a log passes the quick check and is not intercepted will `getFormattedMessage()` be called to generate the message text. * **Step D: Cache Check.** Calculate the hash value of the log content to check if it exists in the cache. If it does, return `DENY` immediately to avoid redundant computation. * **Step E: Whitelist Check (`excludePatterns`).** If the log matches a whitelist regex, return `NEUTRAL`. The whitelist has the highest priority and is used to protect important logs. * **Step F: Exact Match Check (`exactMatches`).** If the log message matches a configured string exactly, return `DENY`. * **Step G: Regex Rule Check (`filterRules`).** If the log message matches a configured regular expression, return `DENY`. 8. **Final Verdict**: * If any of the above interception conditions match, we return `Result.DENY`. Upon receiving `DENY`, Log4j immediately discards the log, and it will not appear in the console or file. * If none match, we return `Result.NEUTRAL`. Log4j considers the filter to have "no opinion" and continues to pass the log to the next processor, eventually displaying it normally. --- ### Part 2: Practical Case Analysis and Configuration Let's look at this log: ```text [241... 00:32:22.574] [Render thread/WARN] [net.minecraft.client.renderer.ShaderInstance/]: Shader rendertype_entity_translucent_emissive could not find sampler named Sampler2 in the specified shader program. ``` #### 1. Log Entry Dissection We need to break down this log into several key parts: | Log Fragment | Meaning | Corresponding Config Item | Note | | :--- | :--- | :--- | :--- | | `WARN` | **Log Level** | `logLevels` | Indicates this is a warning, not an error or info. | | `net.minecraft.client.renderer.ShaderInstance` | **Logger Name** | `loggerNames` | The fully qualified name of the Java class that emitted this log. | | `Shader ... program.` | **Log Message** | `filterRules`, `exactMatches` | The specific error content. | #### 2. How to determine which configuration item it belongs to? * If you want to **block all messages emitted by a certain class/mod** (e.g., I'm tired of seeing all errors from this Shader class), you should use **`loggerNames`**. * If you want to **block all messages of a certain level** (e.g., I don't want to see any WARN level messages), you should use **`logLevels`**. * If you want to **precisely block this one sentence** (even if it only appears once), you should use **`exactMatches`**. * If you want to **fuzzily block this type of error** (e.g., regardless of whether it can't find Sampler1 or Sampler2, or which Shader it is, just block it if it's "cannot find sampler"), you should use **`filterRules`**. #### 3. Practical Configuration Solutions For this specific Shader error, we have four filtering strategies. Please choose according to your needs: ##### Solution A: Precisely filter this error (Recommended - Use `filterRules`) The core feature of this log is "cannot find sampler". We can write a regular expression that covers all cases where a sampler is not found, without affecting other logs. **Applicable Scenario**: You consider all warnings about missing shader samplers to be irrelevant and want to block them all. **Configuration Code**: ```toml # Explanation: .* means any character, matching all logs containing "could not find sampler named", regardless of what comes before or after. filterRules = [".*could not find sampler named.*"] ``` ##### Solution B: Only block this specific long sentence (Use `exactMatches`) If you only want to block the specific warning about `Sampler2` not being found, but keep other Shader warnings. **Applicable Scenario**: Extremely precise strike, no collateral damage. **Configuration Code**: ```toml # Must be exactly the same as the text in the log (usually excluding timestamp and thread name, only including the content after the colon) exactMatches = ["Shader rendertype_entity_translucent_emissive could not find sampler named Sampler2 in the specified shader program."] ``` ##### Solution C: Block all logs from the ShaderInstance class (Use `loggerNames`) If the `ShaderInstance` class is very noisy and you don't want to see anything it outputs at all. **Applicable Scenario**: Aggressive filtering. **Warning**: If this class outputs serious error logs later, you won't see them either. **Configuration Code**: ```toml # As long as the log source is net.minecraft.client.renderer.ShaderInstance, block everything. loggerNames = ["net.minecraft.client.renderer.ShaderInstance"] ``` ##### Solution D: Block all WARN level logs (Use `logLevels`) **Applicable Scenario**: **Not Recommended**. This will block all warning messages, potentially causing you to miss potential issues that really need attention. **Configuration Code**: ```toml logLevels = ["WARN"] ```