日志记录

Neo4j 提供日志用于监控。日志存储在 logs 目录中。如果您想使用自定义目录,请在 neo4j.conf 文件中通过参数 server.directories.logs 设置该目录的路径。

日志文件

下表描述了 Neo4j 中可用的日志文件及其默认配置。哪些日志已启用或禁用在 neo4j.conf 文件中配置。

表 1. Neo4j 日志文件
文件名 描述 配置 默认

neo4j.log

记录关于 Neo4j 的一般信息。对于 Debian 和 RPM 软件包,运行 journalctl --unit=neo4j

true

debug.log

记录 Neo4j 客户支持调查问题所需的信息。强烈建议保持启用状态,并且不要更改 debug.log 格式。如果您需要不同格式的 debug.log 消息,请创建额外的 Appender。从 Neo4j 2025.01 开始,默认格式为 JSON。

true

http.log

记录关于 HTTP API 的信息。

false

gc.log

记录 JVM 提供的信息。

详情请参见配置垃圾回收日志

false

query.log

企业版记录执行时间超过指定阈值的查询信息。必须是 INFOVERBOSEOFF 之一。

  • INFO 记录超过给定阈值的查询。

  • VERBOSE 记录所有查询的开始和结束。

  • OFF 禁用 query.log

详情请参见配置查询日志

VERBOSE

security.log

企业版记录安全事件信息。

true

service-out.log

Windows安装或运行 Windows 服务时的控制台输出日志。

service-error.log

Windows记录安装或运行 Windows 服务时遇到的错误信息。

neo4j-admin-exception-trace-yyyy-MM-dd.HH.mm.ss.log

2025.01 版新增 将执行 neo4j-admin 命令时发生的异常记录到单独的日志文件中。例如,neo4j-admin-exception-trace-2025-01-31.19.31.25.log

neo4j-admin-import-yyyy-MM-dd.HH.mm.ss.log

2025.01 版新增 将使用 neo4j-admin database import 命令时的导入过程信息记录到单独的日志文件中。例如,neo4j-admin-import-2025-01-31.19.31.25.log

默认日志配置

Neo4j 使用 Log4j 2 进行日志记录。日志配置位于 conf 目录中,包含两个文件

  • user-logs.xml — 提供 neo4j.log 的配置。

  • server-logs.xml — 提供 debug.loghttp.logquery.logsecurity.log 的配置。

gc.log 由 Java 虚拟机(JVM) 处理,并使用 JVM 参数进行配置。详情请参见配置垃圾回收日志

从 Neo4j 2025.01 开始,默认配置文件位于 server.directories.configuration=conf 目录中。因此,配置文件的默认路径是 <home>/conf/user-logs.xml<home>/conf/server-logs.xml。如果您为 Log4j 配置文件使用自定义目录,请在 neo4j.conf 文件中更新您的 XML 文件路径,使其依赖于 <conf> 而不是 <home>。例如,server.logs.user.config=path/to/your/conf/user-logs.xmlserver.logs.config=path/to/your/conf/server-logs.xml

每个配置文件包含两个主要元素:AppendersLoggers

Appenders 元素中,您可以定义
  • 输出位置,例如,文件、控制台、网络套接字等。

  • 输出格式,例如,纯文本、JSON、CSV 等。

  • 文件何时滚动以及在删除之前保留多少历史文件。

  • 是否以及如何发布日志事件。

Loggers 元素中,您可以定义
  • 哪些日志事件将被捕获并发送到哪个 Appender

  • 要捕获的日志事件的日志级别。

  • 日志事件是否转发到其他 Loggers

详情请参见 Log4j 2 官方配置文档

以下示例显示了 user-logs.xml 文件的默认配置。

默认 user-logs.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<!--

    Copyright (c) "Neo4j"
    Neo4j Sweden AB [https://neo4j.ac.cn]
    This file is a commercial add-on to Neo4j Enterprise Edition.

-->
<!--
    This is a log4j 2 configuration file that provides maximum flexibility.

    All configuration values can be queried with the lookup prefix "config:". You can, for example, resolve
    the path to your neo4j home directory with ${config:dbms.directories.neo4j_home}.

    Please consult https://logging.apache.ac.cn/log4j/2.x/manual/configuration.html for instructions and
    available configuration options.
-->
<Configuration status="ERROR" monitorInterval="30" packages="org.neo4j.logging.log4j"> \ (1)

    <Appenders> \ (2)
        <RollingRandomAccessFile name="Neo4jLog" fileName="${config:server.directories.logs}/neo4j.log" (3)
                                 filePattern="$${config:server.directories.logs}/neo4j.log.%02i"> (4)
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZ}{GMT+0} %-5p %m%n"/> (6)
            <Policies> \ (7)
                <SizeBasedTriggeringPolicy size="20 MB"/> \ (8)
            </Policies>
            <DefaultRolloverStrategy fileIndex="min" max="7"/> \ (9)
        </RollingRandomAccessFile>

        <!-- Only used by "neo4j console", will be ignored otherwise -->
        <Console name="ConsoleAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZ}{GMT+0} %-5p %m%n"/>
        </Console>
    </Appenders>

    <Loggers> \ (10)
        <!-- Log level for the neo4j log. One of DEBUG, INFO, WARN, ERROR or OFF -->
        <Root level="INFO"> \ (11)
            <AppenderRef ref="Neo4jLog"/>
            <AppenderRef ref="ConsoleAppender"/>
        </Root>
    </Loggers>

</Configuration>

以下示例显示了 server-logs.xml 文件的默认配置。

默认 server-logs.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<!--

    Copyright (c) "Neo4j"
    Neo4j Sweden AB [https://neo4j.ac.cn]
    This file is a commercial add-on to Neo4j Enterprise Edition.

-->
<!--
    This is a log4j 2 configuration file.

    Please keep the original "debug.log" as is, to make sure enough data is captured in of case errors
    in a format that neo4j support engineers and developers can work with. Changing the "debug.log" format
    can interfere with neo4j's ability to offer customer support and invalidate your support warranty.

    If you require the "debug.log" messages in a different format you can copy the Appender and change the
    filename. See Neo4j documentation.

    All configuration values can be queried with the lookup prefix "config:". You can for example, resolve
    the path to your neo4j home directory with ${config:dbms.directories.neo4j_home}.

    Please consult https://logging.apache.ac.cn/log4j/2.x/manual/configuration.html for instructions and
    available configuration options.
-->
<Configuration status="ERROR" monitorInterval="30" packages="org.neo4j.logging.log4j"> \ (1)
    <Appenders> \ (2)
        <!-- Neo4j debug.log, do not change. Required by Neo4j customer support. -->
        <RollingRandomAccessFile name="DebugLog" fileName="${config:server.directories.logs}/debug.log" \ (3)
                                 filePattern="$${config:server.directories.logs}/debug.log.%02i"> \ (4)
            <!-- JSON format -->
            <JsonTemplateLayout eventTemplateUri="classpath:org/neo4j/logging/StructuredLayoutWithMessage.json"/> \ (5)

            <!-- Text format -->
            <!-- <Neo4jDebugLogLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZ}{GMT+0} %-5p [%c{1.}] %m%n"/> -->  \ (6)

            <Policies> \ (7)
                <SizeBasedTriggeringPolicy size="20 MB"/> \ (8)
            </Policies>
            <DefaultRolloverStrategy fileIndex="min" max="7"/> \ (9)
        </RollingRandomAccessFile>

        <RollingRandomAccessFile name="HttpLog" fileName="${config:server.directories.logs}/http.log"
                                 filePattern="$${config:server.directories.logs}/http.log.%02i">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZ}{GMT+0} %-5p %m%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="20 MB"/>
            </Policies>
            <DefaultRolloverStrategy fileIndex="min" max="5"/>
        </RollingRandomAccessFile>

        <RollingRandomAccessFile name="QueryLog" fileName="${config:server.directories.logs}/query.log"
                                 filePattern="$${config:server.directories.logs}/query.log.%02i">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZ}{GMT+0} %-5p %m%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="20 MB"/>
            </Policies>
            <DefaultRolloverStrategy fileIndex="min" max="7"/>
        </RollingRandomAccessFile>

        <RollingRandomAccessFile name="SecurityLog" fileName="${config:server.directories.logs}/security.log"
                                 filePattern="$${config:server.directories.logs}/security.log.%02i">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZ}{GMT+0} %-5p %m%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="20 MB"/>
            </Policies>
            <DefaultRolloverStrategy fileIndex="min" max="7"/>
        </RollingRandomAccessFile>
    </Appenders>

    <Loggers> \ #10>
        <!-- Log levels. One of DEBUG, INFO, WARN, ERROR or OFF -->

        <!-- The debug log is used as the root logger to catch everything -->
        <Root level="INFO"> \ (11)
            <AppenderRef ref="DebugLog"/> <!-- Keep this -->
        </Root>

        <!-- The query log, must be named "QueryLogger" -->
        <Logger name="QueryLogger" level="INFO" additivity="false"> \ (12)
            <AppenderRef ref="QueryLog"/>
        </Logger>

        <!-- The http request log, must be named "HttpLogger" -->
        <Logger name="HttpLogger" level="INFO" additivity="false">
            <AppenderRef ref="HttpLog"/>
        </Logger>

        <!-- The security log, must be named "SecurityLogger" -->
        <Logger name="SecurityLogger" level="INFO" additivity="false">
            <AppenderRef ref="SecurityLog"/>
        </Logger>
    </Loggers>
</Configuration>
1 配置标签,monitorInterval 为 30 秒,包命名空间为 org.neo4j.logging.log4j
监控间隔告诉 Log4j 定期检查 XML 文件是否有更改,如果检测到更改则重新加载文件。
包命名空间允许通过 ${config:<setting>} 访问 Neo4j 配置查找。
2 Appenders 用于定义日志消息的写入位置。appender 的 name 必须唯一,因为它被 logger 在引用 appender 时使用。Neo4j 默认的 appenders 写入 debug.loghttp.logquery.logsecurity.log
3 默认情况下,Neo4j 使用 <RollingRandomAccessFile> appender,因为它性能非常好,总是写入缓冲区。但是,如果服务器崩溃,最后的日志消息可能会丢失。如果您不能接受这一点,请改用 <RollingFile> appender。有关更多信息,请参见Appenders
4 filePattern 指定文件滚动时使用的文件模式。当文件达到定义的触发器时,该模式会将文件重命名为 debug.log.01http.log.01
5 JsonTemplateLayout 布局用于以 JSON 格式格式化日志消息。从 Neo4j 2025.01 开始,默认的 debug.log 格式是 JSON,建议保持启用以确保最佳支持。如果您需要不同格式的 debug.log 消息,请创建额外的 Appender,因为默认的 Appender 被 Neo4j 支持团队使用。如果您需要使用文本格式,可以取消注释条目 <6>。
6 PatternLayout 定义了 appender 的布局,在本例中使用了 GMT+2 时区。请注意,这在 5.x 系列中使用,现在默认已禁用。有关更多信息,请参见日志布局
7 Policies 元素定义了文件何时滚动以及保留多少历史文件。
8 SizeBasedTriggeringPolicy 定义了文件何时滚动。在本例中,当文件大小达到 20 MB 时,文件根据 filePattern 重命名,并且日志文件重新开始。在 Neo4j 4.0 中,这是通过参数 dbms.logs.user.rotation.size 配置的。
9 DefaultRolloverStrategy 定义了要保留多少历史文件。
fileIndex=min 表示最小值/最低编号是最新的一个。
max 属性定义了在删除之前保留的历史文件数量,在本例中为 7 个文件。在 Neo4j 4.0 中,这是通过参数 dbms.logs.user.rotation.keep_number 配置的。
10 Loggers 用于定义日志级别以及日志消息要使用的 appender。logger 通过 name 属性引用。有关更多信息,请参见Loggers
11 根 logger 是一个“全捕获”logger,它捕获所有未被其他 logger 捕获的内容,并将其发送到 AppenderRef 元素中指定的 appender。根 logger 由 Root 元素引用。它可以设置为 DEBUGINFOWARNERROROFF。默认日志级别是 INFO
12 您还可以定义自定义 logger 以捕获特定的日志事件并将其发送到 AppenderRef 元素中指定的 appender。例如,QueryLogger logger(在 server-logs.xml 中配置)用于捕获日志级别为 INFO 或更高的日志事件,并将其发送到 QueryLog appender。
additivity="false" 设置为完全消费日志事件,不将其发送到根 logger。
如果设置了 additivity="true"(这是默认值),日志事件也会发送到根 logger。

高级日志配置

默认日志配置是一个很好的起点,但您可能希望根据自己的需求进行自定义。以下部分描述了一些 Log4j 配置元素以及如何使用它们来自定义日志配置。有关更多信息和更高级的自定义,例如过滤和扩展,请参见 Log4j 官方配置文档

Appenders

所有 Log4j 标准 appenders 在 Neo4j 中都可用。有关更多详细信息,请参见 Log4j 官方 appenders 文档

最常见的几个 appender 是 <RollingRandomAccessFile><RollingFile><Console>

<RollingRandomAccessFile> appender

<RollingRandomAccessFile> 是 Neo4j 中的默认 appender。它性能非常好,对系统影响小,因为它总是写入缓冲区。但是,日志事件可能不会立即可见,并且如果服务器崩溃,最后的日志消息可能会丢失。此 appender 使用 filePattern 属性配置,该属性指定文件滚动时使用的文件模式。当文件达到定义的触发器时,该模式会将文件重命名为 debug.log.01http.log.01

可能的触发器是 SizeBasedTriggeringPolicyTimeBasedTriggeringPolicySizeBasedTriggeringPolicy 定义文件何时滚动,在本例中是当文件大小达到 20 MB 时。TimeBasedTriggeringPolicy 定义文件何时基于时间滚动,在本例中是每天。

DefaultRolloverStrategy 定义了要保留多少历史文件以及哪个文件作为最新的文件。fileIndex=min 表示最小值/最低编号是最新的一个。max 属性定义了在删除之前保留的历史文件数量,在本例中为 7 个文件。

有关更多信息,请参见 Log4j 官方 RollingRandomAccessFile Appender 文档

<RollingFile> appender

<RollingFile> appender 与 <RollingRandomAccessFile> 非常相似,但它将日志事件写入文件。当满足某些条件时,它会进行滚动。标准方案是每天保留一个日志文件,或者在达到特定大小时滚动日志文件。

每日创建一个新日志文件的滚动文件 appender 示例
<RollingFile name="myLog" fileName="${config:server.directories.logs}/my.log"
                       filePattern="${config:server.directories.logs}/my-%d{yyyy-MM-dd}.log">
  <!-- Layout -->
  <Policies>
      <TimeBasedTriggeringPolicy />
  </Policies>
</RollingFile>

滚动还支持已滚动文件的压缩。将 .gz.zip.bz2.deflate.pack200 中的一个作为后缀添加到 filePattern 属性中,将使文件使用相应的压缩方案进行压缩。

带 zip 压缩的滚动文件 appender 示例
<RollingFile name="myLog" fileName="${config:server.directories.logs}/my.log"
                       filePattern="${config:server.directories.logs}/my.%i.log.zip">
  <!-- Layout -->
  <Policies>
      <SizeBasedTriggeringPolicy size="20 MB"/>
  </Policies>
</RollingFile>

<Console> appender

控制台 appender 将日志事件输出到 stdoutstderr。它仅由“neo4j console”使用。

控制台 appender 示例
<Console name="console" target="SYSTEM_OUT"> <!-- or SYSTEM_ERR -->
  <PatternLayout pattern="%m%n"/>
</Console>

日志布局

日志文件可以通过多种不同的方式写入,这些方式被称为布局。Neo4j 捆绑了 Log4j 2 的所有默认布局,以及一些 Neo4j 特有的布局。有关默认 Log4j 2 布局的更多详细信息,请参见 Log4j 官方文档

<PatternLayout>

<PatternLayout> 是最常见的布局。它是一个灵活的布局,可通过模式字符串配置,该字符串在 pattern 属性中指定。例如

<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZ}{GMT+0} %-5p [%c{1.}] %m%n"/>

pattern 由不同的转换器组成,这些转换器以 % 为前缀。转换器将替换为日志事件中的相应值。

表 2. 模式布局转换器示例
转换器 描述

%d{日期模式}{时区}

日志事件的日期。时区是可选的。如果省略,则使用系统时间。

%p

事件的日志级别。可以是 DEBUGINFOWARNERROR。在 % 符号和 p 之间添加 -5 会将级别填充为正好 5 个字符长。

%c

日志事件源自的类。在 {1.} 之后添加会压缩包名,例如 org.apache.commons.Foo 将变为 o.a.c.Foo

%m

日志事件的日志消息。

%n

系统特定的换行符。

有关所有可用转换器,请查阅 Log4j 2 模式布局文档

<JsonTemplateLayout>

<JsonTemplateLayout> 等同于模式布局,用于以 JSON 格式格式化日志消息。

从 Neo4j 2025.01 开始,JSON 是 debug.log 的默认格式。强烈建议不要更改 debug.log 格式,因为 Neo4j 客户支持需要它来调查问题。如果您需要不同格式的 debug.log 消息,请创建额外的 Appender。

配置 JSON 模板布局有两种方式。

  • 您可以指定一个 JSON 事件模板文件,布局将使用该文件。JSON 模板文件可以位于文件系统上。

    <JsonTemplateLayout eventTemplateUri="file://path/to/template.json"/>
  • JSON 事件模板文件可以嵌入在 XML 配置中

    <JsonTemplateLayout>
      <eventTemplate>
        <![CDATA[
          {
            "time": { "$resolver": "timestamp",
              "pattern": { "format": "yyyy-MM-dd HH:mm:ss.SSSZ", "timeZone": "UTC" }
            },
            "level": { "$resolver": "level", "field": "name" },
            "message": { "$resolver": "message" },
            "includeFullMap": { "$resolver": "map", "flatten": true },
            "stacktrace": { "$resolver": "exception", "field": "message" }
          }
        ]]>
      </eventTemplate>
    </JsonTemplateLayout>

还有一些内置模板可从 classpath 中获得,例如

<JsonTemplateLayout eventTemplateUri="classpath:org/neo4j/logging/StructuredJsonLayout.json"/>
表 3. 可用的内置模板
eventTemplateUri 描述

classpath:org/neo4j/logging/StructuredJsonLayout.json

结构化日志消息的布局。仅适用于 query.logsecurity.log

classpath:org/neo4j/logging/StructuredLayoutWithMessage.json

用于记录 JSON 消息的通用布局。可用于任何日志文件。

classpath:org/neo4j/logging/QueryLogJsonLayout.json

向后兼容的 JSON 布局,将匹配 Neo4j 4.x 查询日志。

classpath:LogstashJsonEventLayoutV1.json

classpath:GelfLayout.json

Graylog 扩展日志格式 (GELF) 有效负载规范,带额外的 _thread_logger 字段。

classpath:GcpLayout.json

Google Cloud Platform 结构化日志记录,带额外的 _thread_logger_exception 字段。

classpath:JsonLayout.json

与灵活性较低的 <JsonLayout> 布局相同。

有关更多信息,请参见 Log4j 官方文档

<Neo4jDebugLogLayout>

<Neo4jDebugLogLayout> 布局与 PatternLayout 基本相同。主要区别在于日志文件开头会注入一个包含对 Neo4j 开发者有用的诊断信息的头部。此布局通常仅用于 debug.log 文件。

Neo4j 调试日志布局的使用示例
<Neo4jDebugLogLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZ}{GMT+0} %-5p [%c{1.}] %m%n"/>

过滤器

您还可以配置过滤器以确定是否发布以及如何发布日志事件。详情请参见 Log4j 官方文档

插件

您还可以通过将插件放入 plugin 目录来将它们添加到 Log4j。详情请参见 Log4j 官方插件文档

Loggers

Loggers 将日志事件转发到 appenders。可以有任意数量的 <Logger> 元素,但只有一个 <Root> logger 元素。Loggers 可以是叠加的。一个叠加的 logger 将日志事件转发到其 appender(s) 并将日志事件传递给下一个匹配的 logger。一个非叠加的 logger 将日志事件转发到其 appender(s) 然后丢弃该事件。根 logger 是一个特殊的 logger,它匹配所有内容,因此如果另一个 logger 没有捕获日志事件,根 logger 将会捕获。因此,最佳实践是始终包含一个根 logger,以确保不会遗漏任何日志事件。

Loggers 配置
<Configuration>
    <!-- Appenders -->
    <Loggers>
        <Root level="WARN">
            <AppenderRef ref="DebugLog"/>
        </Root>

        <Logger name="HttpLogger" level="INFO" additivity="false">
            <AppenderRef ref="HttpLog"/>
        </Logger>
    </Loggers>
</Configuration>

logger 有一个 level 用于过滤日志事件。一个级别还可以包括不同严重程度的级别。例如,level="INFO" 的 logger 会转发 INFOWARNERROR 级别的日志事件。level="WARN" 的 logger 只会记录 WARNERROR 事件。

下表列出了 Neo4j 引发的所有日志级别及其严重性级别

表 4. 日志级别
消息类型 严重性级别 描述

DEBUG

低严重性

报告引发错误的详细信息和可能的解决方案。

INFO

低严重性

报告状态信息和不严重的错误。

WARN

低严重性

报告需要关注但不严重的错误。

ERROR

高严重性

报告阻止 Neo4j 服务器运行且必须立即解决的错误。

有关 loggers 的更多详细信息,请参见 Log4j 官方文档 → 配置 Loggers

配置垃圾回收日志

垃圾回收日志,简称 GC 日志,是特殊的,不能用 Log4j 2 配置。GC 日志由 Java 虚拟机(JVM) 处理,必须直接传递给命令行。为了简化此过程,Neo4j 在 neo4j.conf 中公开了以下设置

表 5. 垃圾回收日志配置
垃圾回收日志配置 默认值 描述

server.logs.gc.enabled

false

启用垃圾回收日志记录。

server.logs.gc.options

-Xlog:gc*,safepoint,age*=trace

垃圾回收日志记录选项。有关可用选项,请查阅所用 JVM 发行版的文档。

server.logs.gc.rotation.keep_number

5

垃圾回收日志的最大历史文件数。

server.logs.gc.rotation.size

20MB

垃圾回收日志轮换的阈值大小。

配置安全日志

Neo4j 提供安全事件日志记录,记录所有安全事件。当配置 dbms.security.auth_enabled 设置为 true(这是默认值)时,安全日志会自动启用。它确保所有对 Neo4j 的请求都经过身份验证。有关安全日志的其他配置,请参见 <NEO4J_HOME>/conf/server-logs.xml

对于原生用户管理,以下操作会被记录

  • 登录尝试 — 默认情况下,成功和不成功的登录都会被记录。

  • 所有针对 system 数据库运行的管理命令

  • 基于角色的访问控制中的授权失败。

如果使用 LDAP 作为身份验证方法,一些 LDAP 配置错误的情况也会被记录,以及 LDAP 服务器通信事件和故障。

如果预期有许多程序化交互,建议通过在 neo4j.conf 文件中设置 dbms.security.log_successful_authentication 参数来禁用成功登录的日志记录

dbms.security.log_successful_authentication=false

安全日志可以使用 JSON 布局。要更改格式,SecurityLogger 的布局必须从使用 PatternLayout 更改为

<RollingRandomAccessFile name="SecurityLog" fileName="${config:server.directories.logs}/security.log"
                                 filePattern="$${config:server.directories.logs}/security.log.%02i">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZ}{GMT+0} %-5p %m%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="20 MB"/>
            </Policies>
            <DefaultRolloverStrategy fileIndex="min" max="7"/>
</RollingRandomAccessFile>

使用 JsonTemplateLayout

<RollingRandomAccessFile name="SecurityLog" fileName="${config:server.directories.logs}/security.log"
                                 filePattern="$${config:server.directories.logs}/security.log.%02i">
            <JsonTemplateLayout eventTemplateUri="classpath:org/neo4j/logging/StructuredJsonLayout.json"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="20 MB"/>
            </Policies>
            <DefaultRolloverStrategy fileIndex="min" max="7"/>
 </RollingRandomAccessFile>

以下信息以 JSON 格式提供

表 6. JSON 格式日志条目
名称 描述

time

日志消息的时间戳。

level

日志级别。

type

始终是 security

source

连接详情。

database

执行命令的数据库名称。此字段是可选的,因此不会为所有安全事件填充。

username

连接到安全事件的用户。此字段已被 executingUser 弃用。

executingUser

触发安全事件的用户名。与 authenticatedUser 相同或是一个被模拟的用户。

authenticatedUser

已验证身份并连接到安全事件的用户名。

message

日志消息。

stacktrace

如果日志消息关联有堆栈跟踪,则包含此字段。

纯文本格式的安全日志示例

2019-12-09 13:45:00.796+0000 INFO  [johnsmith]: logged in
2019-12-09 13:47:53.443+0000 ERROR [johndoe]: failed to log in: invalid principal or credentials
2019-12-09 13:48:28.566+0000 INFO  [johnsmith]: CREATE USER janedoe SET PASSWORD '********' CHANGE REQUIRED
2019-12-09 13:48:32.753+0000 INFO  [johnsmith]: CREATE ROLE custom
2019-12-09 13:49:11.880+0000 INFO  [johnsmith]: GRANT ROLE custom TO janedoe
2019-12-09 13:49:34.979+0000 INFO  [johnsmith]: GRANT TRAVERSE ON GRAPH * NODES A, B (*) TO custom
2019-12-09 13:49:37.053+0000 INFO  [johnsmith]: DROP USER janedoe
2019-12-09 13:52:24.685+0000 INFO  [johnsmith:alice]: impersonating user alice logged in

配置查询日志

查询日志默认启用,并由设置 db.logs.query.enabled 控制。它有助于您分析长时间运行的查询,并且不影响系统性能。默认是记录所有查询,但建议只记录超过特定阈值的查询。

配置设置

参数 db.logs.query.enabled 可用的值如下

表 7. db.logs.query.enabled
选项 描述

OFF

完全禁用日志记录。

INFO

在成功或失败的查询结束时记录日志。db.logs.query.threshold 参数用于确定查询日志记录的阈值。如果查询的执行时间超过此阈值,则记录该查询。将阈值设置为 0s 会记录所有查询。

VERBOSE

默认记录所有查询的开始和结束,无论 db.logs.query.threshold 如何。

查询日志记录的以下配置设置可用

表 8. 查询日志配置
查询日志配置 默认值 描述

db.logs.query.early_raw_logging_enabled

false

记录查询文本和参数,不混淆密码。这允许在解析开始之前更早地记录查询。

db.logs.query.enabled

VERBOSE

记录已执行的查询。

db.logs.query.max_parameter_length

2147483647

此配置选项允许您设置日志中包含的最大参数长度。超过此长度的参数将被截断并附加 ...。这适用于查询中的每个参数。

db.logs.query.obfuscate_literals

false

如果为 true,则在写入日志之前混淆所有查询文字。当 Cypher 查询暴露敏感信息时,这很有用。

节点标签、关系类型和映射属性键仍会显示。更改此设置不会影响缓存的查询。因此,如果您希望此更改立即生效,还必须清除查询缓存;CALL db.clearQueryCaches()
另外,请记住,如果 Neo4j 收到无法解析的格式错误的查询,它无法混淆其文字(因为它不知道哪些部分是文字),因此,查询文本将不会包含在任何日志记录中。

这不会混淆参数中的文字。如果日志中不需要参数值,请设置 db.logs.query.parameter_logging_enabled=false

db.logs.query.parameter_logging_enabled

true

记录正在日志记录的已执行查询的参数。如果您不想显示敏感信息,可以禁用此配置设置。

db.logs.query.plan_description_enabled

false

此配置选项允许您记录每个查询的查询计划。查询计划以描述表的形式显示,对调试很有用。每次运行 Cypher 查询时,它都会生成并使用一个执行代码的计划。生成的计划可能会受到数据库更改的影响,例如添加新索引。因此,无法历史性地查看原始查询执行使用了哪个计划。

启用此选项会对数据库性能产生影响,因为准备并将计划包含在 query log 中会产生开销。不建议日常使用。

db.logs.query.threshold

0s

如果查询执行时间超过此阈值,则查询完成后(如果查询日志记录设置为 INFO)将被记录。阈值为 0 秒表示记录所有查询。

db.logs.query.transaction.enabled

OFF

在查询日志中跟踪事务的开始和结束。日志条目将写入 query log。它们包括特定查询的事务 ID 以及事务的开始和结束。您还可以选择日志级别(OFFINFOVERBOSE)。如果选择 INFO,则必须超过写入日志前的时间(db.logs.query.transaction.threshold)。

db.logs.query.transaction.threshold

0s

如果事务打开时间超过此阈值(持续时间),则在事务完成后记录该事务,前提是事务日志记录设置为 INFO。默认为 0 秒,这意味着所有事务都会被记录。这在识别查询执行和事务提交之间存在显著时间间隔的地方(特别是在围绕锁定的性能分析中)可能很有用。

配置简单查询日志记录

在此示例中,查询日志记录设置为 INFO,所有其他查询日志参数均使用默认值。

db.logs.query.enabled=INFO

以下是使用此基本配置的查询日志示例

2017-11-22 14:31 ... INFO  9 ms: bolt-session	bolt	johndoe	neo4j-javascript/1.4.1		client/127.0.0.1:59167	...
2017-11-22 14:31 ... INFO  0 ms: bolt-session	bolt	johndoe	neo4j-javascript/1.4.1		client/127.0.0.1:59167	...
2017-11-22 14:32 ... INFO  3 ms: server-session	http	127.0.0.1	/db/data/cypher	neo4j - CALL dbms.procedures() - {}
2017-11-22 14:32 ... INFO  1 ms: server-session	http	127.0.0.1	/db/data/cypher	neo4j - CALL dbms.showCurrentUs...
2017-11-22 14:32 ... INFO  0 ms: bolt-session	bolt	johndoe	neo4j-javascript/1.4.1		client/127.0.0.1:59167	...
2017-11-22 14:32 ... INFO  0 ms: bolt-session	bolt	johndoe	neo4j-javascript/1.4.1		client/127.0.0.1:59167	...
2017-11-22 14:32 ... INFO  2 ms: bolt-session	bolt	johndoe	neo4j-javascript/1.4.1		client/127.0.0.1:59261	...

配置更详细的查询日志记录

在此示例中,查询日志以及一些额外的日志记录都已启用

db.logs.query.enabled=INFO
db.logs.query.parameter_logging_enabled=true
db.logs.query.threshold=<appropriate value>

以下示例查询在 Movies 数据库上运行

MATCH (n:Person {name:'Tom Hanks'})-[:ACTED_IN]->(n1:Movie)<-[:DIRECTED]-(n2:Person {name:"Tom Hanks"}) RETURN n1.title

<.file>query.log 中相应的查询日志为

2017-11-23 12:44:56.973+0000 INFO  1550 ms: (planning: 20, cpu: 920, waiting: 10) - 13792 B - 15 page hits, 0 page faults - bolt-session	bolt	neo4j	neo4j-javascript/1.4.1		client/127.0.0.1:58189	server/127.0.0.1:7687>	neo4j - match (n:Person {name:'Tom Hanks'})-[:ACTED_IN]->(n1:Movie)<-[:DIRECTED]-(n2:Person {name:"Tom Hanks"}) return n1.title; - {} - {}

检查特定查询参数时,一个显而易见但重要的注意事项是,确保您只分析与该特定查询计划相关的条目,而不是例如,每个日志条目中的 CPU、时间、字节等。

以下是与上述查询对应的资源使用参数及其描述的细分

2017-11-23 12:44:56.973+0000

日志时间戳。

INFO

日志类别。

1550 毫秒

查询执行中花费的总累计实际时间。它是规划时间 + CPU + 等待时间 + 任何其他处理时间(例如,获取执行线程所需的时间)的总和。此数字是 CPU 线程每次执行查询时累积的。

规划

指 Cypher 引擎创建查询计划所需的时间。对于重复查询,计划可能会被缓存,因此,此类查询的规划时间将比以前未规划的查询短。在示例中,这为 1550 毫秒的总执行时间贡献了 20 毫秒。

CPU 时间

指执行查询的各个线程所花费的时间,例如,在 08:00 提交一个查询。它使用 CPU 720 毫秒,但随后 CPU 切换到另一个查询,因此第一个查询不再使用 CPU。然后,在 100 毫秒后,它再次获取/使用 CPU 200 毫秒(更多结果需要加载,由客户端通过驱动程序请求),然后查询在 08:01:30 完成,因此总持续时间为 1550 毫秒(包括两次往返的一些往返时间),CPU 时间为 720+200=920 毫秒。

等待

查询在执行前等待的时间(以毫秒为单位),例如,如果现有查询有一个锁,新查询必须等待该锁释放。在示例中,这为 1550 毫秒的总执行时间贡献了 10 毫秒。
重要的是要注意,客户端仅在其记录缓冲区为空时(从服务器进行一次往返可能最终得到多条记录)才从服务器请求数据,并且如果客户端没有及时读取传出缓冲区中的数据,服务器会停止将数据推送到传出缓冲区。因此,这取决于结果集的大小。如果它相对较小并适合一次往返,客户端会一次性接收所有结果,并且服务器完成处理而不会产生任何客户端副作用。同时,如果结果集很大,客户端处理时间将影响总时间,因为它直接与何时从服务器请求新数据相关。

13792 B

已执行查询的已记录分配字节。这是查询生命周期中使用的堆内存量。记录的数字是查询持续时间内的累积值,即,对于内存密集型或长时间运行的查询,该值可能大于当前内存分配。

15 页命中

页命中表示结果从页面缓存返回,而不是从磁盘返回。在这种情况下,页面缓存命中了 15 次。

0 页错误

页错误表示查询结果数据不在 dbms.memory.pagecache 中,因此必须从文件系统获取。在这种情况下,查询结果完全从上面提到的 8 次页面缓存命中返回,因此不需要进行 0 次磁盘命中。

bolt-session

会话类型。

bolt

查询使用的浏览器 ←→ 数据库通信协议。

neo4j

进程 ID。

neo4j-javascript/1.4.1

驱动程序版本。

client/127.0.0.1:52935

查询客户端使用的出站 IP:port

server/127.0.0.1:7687>

服务器监听使用的 IP:port

neo4j

查询执行者的用户名

match (n:Person {name:'Tom Hanks'})-[:ACTED_IN]→(n1:Movie)←[:DIRECTED]-(n2:Person {name:"Tom Hanks"}) return n1.title

执行的查询。

最后两个括号 {} {} 用于查询参数和 txMetaData

将元数据附加到事务

您可以使用内置过程 tx.setMetaData 将元数据附加到事务并在查询日志中打印。

Neo4j 驱动程序也支持将元数据附加到事务。有关更多信息,请参阅相应驱动程序的手册。

每个图应用程序都应遵循一个约定,用于在发送到 Neo4j 的查询中传递元数据

{
  app: "neo4j-browser_v4.4.0", (1)
  type: "system" (2)
}
1 app 可以是用户代理样式的名称加版本。
2 type 可以是以下之一
  • system — 应用程序自动运行的查询。

  • user-direct — 用户直接提交到/通过应用程序的查询。

  • user-action — 用户执行操作后产生的查询。

  • user-transpiled — 从用户输入派生出的查询。

这通常是通过编程方式完成的,但也可以与 Neo4j 开发工具一起使用。
通常,您在一个用户数据库上启动一个事务,并通过调用 tx.setMetaData 将元数据列表附加到该事务。您还可以使用过程 CALL tx.getMetaData() 来显示当前事务的元数据。这些示例使用 Neo4j 浏览器指南中的 MovieGraph 数据集。

示例 1. 使用 cypher-shell,将元数据附加到事务
Cypher Shell 默认总是添加遵循约定的元数据。在此示例中,默认值被覆盖。
neo4j@neo4j> :begin
neo4j@neo4j# CALL tx.setMetaData({app: 'neo4j-cypher-shell_v.4.4.0', type: 'user-direct', user: 'jsmith'});
0 rows
ready to start consuming query after 2 ms, results consumed after another 0 ms
neo4j@neo4j# CALL tx.getMetaData();
+--------------------------------------------------------------------------+
| metadata                                                                 |
+--------------------------------------------------------------------------+
| {app: "neo4j-cypher-shell_v.4.4.0", type: "user-direct", user: "jsmith"} |
+--------------------------------------------------------------------------+

1 row
ready to start consuming query after 37 ms, results consumed after another 2 ms
neo4j@neo4j# MATCH (n:Person) RETURN n  LIMIT 5;
+----------------------------------------------------+
| n                                                  |
+----------------------------------------------------+
| (:Person {name: "Keanu Reeves", born: 1964})       |
| (:Person {name: "Carrie-Anne Moss", born: 1967})   |
| (:Person {name: "Laurence Fishburne", born: 1961}) |
| (:Person {name: "Hugo Weaving", born: 1960})       |
| (:Person {name: "Lilly Wachowski", born: 1967})    |
+----------------------------------------------------+

5 rows
ready to start consuming query after 2 ms, results consumed after another 1 ms
neo4j@neo4j# :commit
query.log 文件中的示例结果
2021-07-30 14:43:17.176+0000 INFO  id:225 - 2 ms: 136 B - bolt-session	bolt	neo4j-cypher-shell/v4.4.0		client/127.0.0.1:54026	server/127.0.0.1:7687>	neo4j - neo4j -
MATCH (n:Person) RETURN n  LIMIT 5; - {} - runtime=pipelined - {app: 'neo4j-cypher-shell_v.4.4.0', type: 'user-direct', user: 'jsmith'}
示例 2. 使用 Neo4j 浏览器,将元数据附加到事务
CALL tx.setMetaData({app: 'neo4j-browser_v.4.4.0', type: 'user-direct', user: 'jsmith'})
MATCH (n:Person) RETURN n LIMIT 5
query.log 文件中的示例结果
2021-07-30 14:51:39.457+0000 INFO  Query started: id:328 - 0 ms: 0 B - bolt-session	bolt	neo4j-browser/v4.4.0		client/127.0.0.1:53666	server/127.0.0.1:7687>	neo4j - neo4j - MATCH (n:Person) RETURN n  LIMIT 5 - {} - runtime=null - {type: 'system', app: 'neo4j-browser_v4.4.0'}
示例 3. 使用 Neo4j Bloom,将元数据附加到事务
CALL tx.setMetaData({app: 'neo4j-browser_v.1.7.0', type: 'user-direct', user: 'jsmith'})
MATCH (n:Person) RETURN n LIMIT 5
query.log 文件中的示例结果
2021-07-30 15:09:54.048+0000 INFO  id:95 - 1 ms: 72 B - bolt-session	bolt	neo4j-bloom/v1.7.0		client/127.0.0.1:54693	server/127.0.0.1:11003>	neo4j - neo4j - RETURN TRUE - {} - runtime=pipelined - {app: 'neo4j-bloom_v1.7.0', type: 'system'}

在 Neo4j 浏览器和 Bloom 中,用户提供的元数据始终被系统元数据替换。

为查询日志使用 JSON 格式

查询日志可以使用 JSON 布局。要更改格式,QueryLogger 的布局必须从使用 PatternLayout 更改为

<RollingRandomAccessFile name="QueryLog" fileName="${config:server.directories.logs}/query.log"
                     filePattern="${config:server.directories.logs}/query.log.%02i">
    <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSSZ}{GMT+0} %-5p %m%n"/>
    <Policies>
        <SizeBasedTriggeringPolicy size="20 MB"/>
    </Policies>
    <DefaultRolloverStrategy fileIndex="min" max="7"/>
</RollingRandomAccessFile>

使用 JsonTemplateLayout

<RollingRandomAccessFile name="QueryLog" fileName="${config:server.directories.logs}/query.log"
                     filePattern="${config:server.directories.logs}/query.log.%02i">
    <JsonTemplateLayout eventTemplateUri="classpath:org/neo4j/logging/QueryLogJsonLayout.json"/>
    <Policies>
        <SizeBasedTriggeringPolicy size="20 MB"/>
    </Policies>
    <DefaultRolloverStrategy fileIndex="min" max="7"/>
</RollingRandomAccessFile>

JSON 格式日志条目

QueryLogJsonLayout.json 模板模仿 4.x 布局并包含以下信息

表 9. JSON 格式日志条目
名称 描述

time

日志消息的时间戳。

level

日志级别。

type

有效选项为 querytransaction

stacktrace

如果日志消息关联有堆栈跟踪,则包含此字段。

如果日志条目类型为 query,则以下附加字段可用

表 10. 日志类型 query 的 JSON 格式日志条目
名称 描述

event

有效选项为 startfailsuccess

id

查询 ID。ID 是递增的,从 1 开始,并在每次 Neo4j 重启时重置。当 db.logs.query.enabledVERBOSE 时包含。

elapsedTimeMs

经过的时间(毫秒)。

planning

花费在规划上的毫秒数。

cpu

CPU 上主动执行所花费的毫秒数。

waiting

等待锁或其他查询所花费的毫秒数,而不是主动运行此查询。

allocatedBytes

查询分配的字节数。

pageHits

页命中数。

pageFaults

页错误数。

source

连接详情。

database

运行查询的数据库名称。如果查询无法解析并路由到数据库,此字段将为 <none>

executingUser

执行查询的用户名。与 authenticatedUser 相同或是一个被模拟的用户。

authenticatedUser

已验证身份并正在执行查询的用户名。

query

查询文本。

queryParameters

查询参数。当 db.logs.query.parameter_logging_enabledtrue 时包含。

runtime

运行查询所使用的运行时。

annotationData

附加到事务的元数据。

failureReason 2025.05 版中已弃用

失败原因。适用时包含。已被 errorInfo 替换。

errorInfo

GQL 错误信息以 JSON 对象形式提供。有关 errorInfo JSON 对象内容的详细信息,请参见GQL 错误信息

transactionId

正在运行查询的事务 ID。

queryPlan

查询计划。当 db.logs.query.plan_description_enabledtrue 时包含。

executionPlanCacheKeyHash

用于缓存执行计划的缓存键的 32 位哈希值。它是一个固定长度的 8 字符十六进制编码整数值字符串。默认仅在 JSON 格式中启用。如果多个查询执行使用相同的缓存执行计划,它们的哈希值应匹配。对于 event=start,值为 00000000

executableQueryCacheHit

查询字符串是否匹配缓存的执行计划。

queryLang 2025.01 版新增

Cypher 版本。

如果日志条目类型为 transaction,则以下附加字段可用

表 11. 日志类型 transaction 的 JSON 格式日志条目
名称 描述

event

有效选项为 startrollbackcommit

database

运行事务的数据库名称。

executingUser

连接到事务的用户名称。与 authenticatedUser 相同或是一个被模拟的用户。

authenticatedUser

已验证身份并连接到事务的用户名。

transactionId

事务 ID。

GQL 错误信息

查询日志在 JSON 对象 errorInfo 下包含 GQL 错误信息。errorInfo 可以包含以下元素

  • GQLSTATUS — 一个 5 个字符长的字母数字代码,用于标识错误。

  • statusDescription — 描述错误的消息。

  • classification — 表示客户端、瞬态和数据库错误分类的错误类型。

  • position — 查询中发生此错误的位置(一个包含 columnoffsetline 字段的 JSON 对象)。

  • cause — 一个 JSON 对象,包含当前 errorInfo JSON 对象的根源 errorInfo JSON 对象。

当异常没有 GQL 状态对象时,将返回默认的 GQLSTATUS 代码 50N42。因此,不要依赖此默认代码非常重要,因为未来的 Neo4j 版本可能会通过向异常添加适当的 GQL 对象来更改它。此外,外部过程的 GQL 代码尚未稳定。

以下是 errorInfo JSON 对象的示例

数据库错误的 errorInfo JSON 对象
...
"errorInfo": {
    "GQLSTATUS": "51N66",
    "statusDescription": "error: system configuration or operation exception - resource exhaustion. Insufficient resources to complete the request.",
    "cause": {
      "GQLSTATUS": "51N55",
      "statusDescription": "error: system configuration or operation exception - cannot create additional database. Failed to create the database `db10`. The limit of databases is reached. Either increase the limit using the config setting dbms.max_databases or drop a database.",
      "classification": "DATABASE_ERROR"
    },
    "classification": "DATABASE_ERROR"
  },
...
客户端错误的 errorInfo JSON 对象
...
"errorInfo": {
    "GQLSTATUS": "42N62",
    "statusDescription": "error: syntax error or access rule violation - variable not defined. Variable `m` not defined.",
    "position": {
      "column": 18,
      "offset": 17,
      "line": 1
    },
    "classification": "CLIENT_ERROR"
  },
"query": "MATCH (n) RETURN m",
...
© . All rights reserved.