如何通过ScriptEngineManager为GraalVM JS引擎配置自定义日志至Eclipse错误日志
将GraalVM TruffleLogger日志转发到Eclipse错误日志的解决方案
核心结论
- 无需修改插件A的ScriptEngine初始化代码,即可附加自定义日志器
- 可以通过程序化方式替换TruffleLogger,将日志转发至Eclipse错误日志
具体实现步骤
1. 获取GraalVM Polyglot Engine实例
GraalVM的JS ScriptEngine本质是JSScriptEngine,可以强制转换后获取底层的Polyglot Engine:
import org.graalvm.js.scriptengine.JSScriptEngine; import org.graalvm.polyglot.Engine; // 假设this.scriptEngine是从ScriptEngineManager获取的实例 JSScriptEngine graalScriptEngine = (JSScriptEngine) this.scriptEngine; Engine polyglotEngine = graalScriptEngine.getPolyglotEngine();
2. 实现自定义TruffleLogger,转发至Eclipse错误日志
实现TruffleLogger接口,将日志事件映射到Eclipse的ILog(错误日志系统):
import org.graalvm.truffle.api.TruffleLogger; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; public class EclipseTruffleLogger implements TruffleLogger { private final ILog eclipseLog; private final String loggerName; private final String pluginId; public EclipseTruffleLogger(ILog eclipseLog, String loggerName, String pluginId) { this.eclipseLog = eclipseLog; this.loggerName = loggerName; this.pluginId = pluginId; } @Override public String getName() { return loggerName; } @Override public boolean isLogEnabled(Level level) { // 根据Eclipse日志配置调整级别过滤逻辑 return switch (level) { case INFO, WARN, ERROR -> true; default -> false; }; } @Override public void log(Level level, String message) { if (!isLogEnabled(level)) return; eclipseLog.log(createStatus(level, message, null)); } @Override public void log(Level level, String message, Throwable thrown) { if (!isLogEnabled(level)) return; eclipseLog.log(createStatus(level, message, thrown)); } private IStatus createStatus(TruffleLogger.Level level, String message, Throwable thrown) { int severity = switch (level) { case INFO -> IStatus.INFO; case WARN -> IStatus.WARNING; case ERROR -> IStatus.ERROR; default -> IStatus.INFO; }; return new Status(severity, pluginId, message, thrown); } // 保留其他默认方法的实现 }
3. 注册自定义日志工厂到Polyglot Engine
将自定义日志器绑定到GraalVM的Engine,替换默认的TruffleLogger:
import org.graalvm.truffle.api.TruffleLoggerFactory; import org.eclipse.core.runtime.Platform; // 获取当前插件的Eclipse日志实例 String pluginId = "com.yourcompany.yourplugin"; // 替换为你的插件ID ILog eclipseLog = Platform.getLog(Platform.getBundle(pluginId)); // 注册自定义日志工厂 polyglotEngine.getOptions().put( TruffleLoggerFactory.LOGGER_FACTORY, (loggerName) -> new EclipseTruffleLogger(eclipseLog, loggerName, pluginId) );
备选方案:通过系统属性提前配置
如果无法在ScriptEngine初始化后获取Engine实例,可以在插件启动时提前设置系统属性,指定自定义日志工厂的全类名:
// 在插件激活类的start方法中设置 System.setProperty( "org.graalvm.truffle.logger.factory", "com.yourcompany.yourplugin.EclipseTruffleLoggerFactory" );
对应的日志工厂类需要实现TruffleLoggerFactory:
import org.graalvm.truffle.api.TruffleLogger; import org.graalvm.truffle.api.TruffleLoggerFactory; import org.eclipse.core.runtime.Platform; public class EclipseTruffleLoggerFactory implements TruffleLoggerFactory { private final ILog eclipseLog; private final String pluginId; public EclipseTruffleLoggerFactory() { this.pluginId = "com.yourcompany.yourplugin"; this.eclipseLog = Platform.getLog(Platform.getBundle(pluginId)); } @Override public TruffleLogger getLogger(String loggerName) { return new EclipseTruffleLogger(eclipseLog, loggerName, pluginId); } }
注意事项
- 确保项目依赖中包含GraalVM JS和Truffle的相关库(
org.graalvm.js、org.graalvm.truffle) - 替换代码中的
pluginId为你实际的Eclipse插件ID - 日志级别过滤逻辑可根据需求调整,匹配Eclipse的日志显示规则
内容的提问来源于stack exchange,提问作者Paul-E
相关产品推荐
相关产品推荐

