我正在尝试调试我正在编写的 Neo4J Server 插件中的问题。有我可以输出的日志吗?在哪里或如何做到这一点并不明显。
2 回答
好问题。我认为您可以使用Java Logging?这应该被路由到正常的日志记录系统。
只需注入org.neo4j.logging.Log
包含 Neo4j 存储过程实现的类即可。
public class YourProcedures {
@Context
public Transaction tx;
@Context
public Log log;
@Procedure(value = "yourProcedure", mode = Mode.READ)
public Stream<YourResult> yourProcedure(@Name("input") String input) {
log.debug("something");
}
}
然后将日志转储到标准 Neo4j 日志文件中。级别由GraphDatabaseSettings.store_internal_log_level
配置控制。级别也可以在运行时更改。只需注入DependencyResolver
bean 并定义这个管理过程。(该框架有监听器连接到重新配置内部日志框架的配置更改。这是我能找到的最简单的解决方案。)
@Context
public DependencyResolver dependencyResolver;
@Procedure(value = "setLogLevel", mode = Mode.DBMS)
@Description("Runtime change of logging level")
public void setLogLevel(@Name("level") String level) {
Config config = dependencyResolver.resolveDependency(Config.class);
config.set(GraphDatabaseSettings.store_internal_log_level, Level.valueOf(level));
}
更新:
这个 ^ 解决方案有效,但是当想要使用 Log4j 中通常的日志记录方式时它是不够的 - 不同的记录器按层次结构组织,每个记录器都有自己的级别。该org.neo4j.logging.Log
组件只是GlobalProcedures
该类的 Log4j 记录器的包装器。此记录器只是层次结构中的许多记录器之一。事实上,包装器阻止了对底层框架更丰富特性的访问。(不幸的是,@Context Log
在类中定义由某些注释限定记录器区分的多个字段YourProcedures
也是不可能的,因为字段注入是由驱动的,因此根据字段类型,Map<Class,instance>
对于任何带注释的字段只有一个可能的实例注入。)@Context-
解决方案 1: 在接受的答案中使用 JUL。缺点是,JUL 无论如何都会将日志事件重定向到底层 Log4j,因此如果在 JUL 中定义了记录器层次结构,则必须将 Log4j 设置为尽可能低的级别,以使 JUL 级别敏感。
解决方案2:
直接使用Log4j(即public static final Logger logger = LogManager.getLogger("some.identifier.in.hierarchy")
在YourProcedures
)。尽管有可能以编程方式重新定义配置存在一些问题,但我放弃了这个解决方案只是因为我在非 docker 环境中部署这个解决方案时遇到了一些问题。
解决方案 3:(最终选择)我定义了自定义组件LogWithHierarchy
(它可以ExtensionFactory
使用 s 从自己加载的内容构建ServiceLoader
- 我在APOC 配置实现中受到启发)。该组件提供表单等API debug(loggerName, message)
。info(loggerName, message)
该组件知道原始Log
,深入到其log4jLoggerContext
并将所有日志记录请求重定向到此中的特定记录器LoggerContext
。日志消息最终以debug.log
. 有了这个解决方案,原始的 log4j 记录器层次结构被充分利用,级别可以在运行时动态更改(setLogLevel
必须更改以在上述操作上进行操作LoggerContext
),并且仍然使用标准 Neo4j 插件支持来实现所有内容。