yumc
本帖最后由 yumc 于 2020-5-13 17:32 编辑

最近需要拦截服务端日志 做转发
然后折腾了半天没折腾出来
有大佬嘛

目前是对插件的Logger加了一个Filter
但是只能拦截到插件自身的日志直接加到Bukkit的Logger上好像又没啥用

enable() {
        try {
            global['logger'].setFilter((record) => {
                this.loggerEvent.emit('log', record.getMessage())
                return true;
            });
        } catch (error) {
            console.error(error);
        }
    }

    disable() {
        try {
            global['logger'].setFilter(null);
            this.loggerEvent.removeAllListeners();
        } catch (error) {
            console.error(error);
        }
    }



谁有能够全局截获日志的方法
另一个就是 怎么获取 发送给ConsoleSender的消息
看了看具体实现 好像直接怼到 System.out 上面了
public class CraftConsoleCommandSender extends ServerCommandSender implements ConsoleCommandSender {

    protected final ConversationTracker conversationTracker = new ConversationTracker();

    protected CraftConsoleCommandSender() {
        super();
    }

    public void sendMessage(String message) {
        sendRawMessage(message);
    }

    public void sendRawMessage(String message) {
        System.out.println(ChatColor.stripColor(message));
    }
}


问题解决了
通过Arthas 导出了Heapdump 分析了一下引用链
最终在 net.minecraft.server.v1_12_R1.MinecraftServer 下面 找到了一个静态字段 LOGGER
最后获取 parent 就好了
nashorn伪代码 在MiaoScript可以运行

enable() {
        try {
            let AbstractAppender = Java.type('org.apache.logging.log4j.core.appender.AbstractAppender');
            let ProxyAppender = Java.extend(AbstractAppender, {
                append: (logEvent) => global.eventCenter.emit('log', logEvent.getMessage().getFormattedMessage())
            })
            Packages.net.minecraft.server.MinecraftServer.field_147145_h
            let logger = Packages.net.minecraft.server.v1_12_R1.MinecraftServer.LOGGER.parent;
            this.tempAppender = new ProxyAppender("ProxyLogger", null, null)
            this.tempAppender.start();
            logger.addAppender(this.tempAppender);
            logger.setAdditive(true);
        } catch (error) {
            console.error(error);
        }
    }

    disable() {
        try {
            let logger = Packages.net.minecraft.server.v1_12_R1.MinecraftServer.LOGGER.parent;
            this.tempAppender.stop();
            logger.removeAppender(this.tempAppender);
        } catch (error) {
            console.error(error);
        }
    }

来自群组: 银河系气功协会

Karlatemp
mc使用log4j,可以直接拦截log4j的日志(就是从log4j入手)

yumc
Karlatemp 发表于 2020-5-13 13:25
mc使用log4j,可以直接拦截log4j的日志(就是从log4j入手)

嗯 那个我写AuthMe的时候用过
但是好像只能拦截插件自己的
我试过设置到Bukkit上 但是好像拦不到

Karlatemp
你可以尝试操作一下RootLogger,没记错的话最终都会走Root Logger

yumc
Karlatemp 发表于 2020-5-13 13:54
你可以尝试操作一下RootLogger,没记错的话最终都会走Root Logger

比较迷幻的是 我获取 Bukkit.getLogger返回的并不是 log4j 的实例
>mpm run org.bukkit.Bukkit.getLogger()
[14:00:16 INFO]: [MS][PM] 运行脚本: org.bukkit.Bukkit.getLogger()
[14:00:16 INFO]: [MS][PM] 返回结果: java.util.logging.Logger@739cb3a2

Karlatemp

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger;

public class JavaTest {


    public static void test() {
        Logger logger = ((Logger) LogManager.getRootLogger());
        logger.addAppender(...);
    }
}

可以试下

Karlatemp
yumc 发表于 2020-5-13 13:55
比较迷幻的是 我获取 Bukkit.getLogger返回的并不是 log4j 的实例

Bukkit.getLogger()获取的是jdk原生日志,属于log4j的一个wrapper通道. 获取Log4j的root logger得用log4j的方法

yumc
Karlatemp 发表于 2020-5-13 13:56
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger;

Appender 推荐用啥呐
自己实现 还是说 继承某个抽象类

yumc
Karlatemp 发表于 2020-5-13 13:59
Bukkit.getLogger()获取的是jdk原生日志,属于log4j的一个wrapper通道. 获取Log4j的root logger得用log4j ...

好像有点问题
我在不同的地方获取 getRootLogger 返回的实例并不是同一个
[15:05:04 INFO]: [MiaoScript] [MiaoConsole] :INFO in 3d7a7912
[15:05:04 INFO]: [MS][PM] 插件 MiaoConsole 重载完成!
[15:05:05 INFO]: [MiaoScript] [MiaoConsole] Netty Channel Pipeline Inject MiaoDetectHandler Successful!
[15:05:10 INFO]: [MS][MiaoConsole] 客户端 /MiaoConsole#87ab59ae 新建连接...
>mpm run Packages.org.apache.logging.log4j.LogManager.getRootLogger()
[15:06:04 INFO]: [MS][PM] 运行脚本: Packages.org.apache.logging.log4j.LogManager.getRootLogger()
[15:06:04 INFO]: [MS][PM] 返回结果: :INFO in 21123a77

轻光233
您好
获取控制台所有输出的问题论坛讨论过,我给出过一个详细的答案,可以直接操作
https://www.mcbbs.net/thread-918684-1-1.html

yumc
轻光233 发表于 2020-5-13 18:46
您好
获取控制台所有输出的问题论坛讨论过,我给出过一个详细的答案,可以直接操作
https://www.mcbbs.net/ ...

嗯 已经分析源码解决了
现在在折腾Sponge的日志拦截
有点小问题