概述

ReadAudit 是一项功能,其中出于审计目的记录了读取访问。你可以使用 @ReadAudit 注释实体 Bean,然后记录对这些 Bean 的读取事件(查询和 L2 缓存中的命中)。

通常需要实现 ReadAuditPrepare 接口。readAuditPrepare.prepare() 方法应使用用户上下文信息(用户 ID、用户 IP 地址等)填充 ReadEvent。

限制

SqlQuery 查询当前未记录到读取审计日志(RawSql 查询包含在读取审计中)。

开始

步骤 1:添加 @ReadAudit

向应该进行读取审计的所有实体 Bean 添加 @ReadAudit 注释。

@ReadAudit
@Entity
@Table(name = "customer")
public class Customer {
...

步骤 2:实现 ReadAuditPrepare

如果你跳过此步骤且不提供 ReadAuditPrepare 实现,则会使用“无操作”实现,并且不会填充用户上下文信息(用户 ID、用户 IP 地址等)。

class MyReadAuditPrepare implements ReadAuditPrepare {

  @Override
  public void prepare(ReadEvent event) {

    // get user context information typically from a
    // ThreadLocal or similar mechanism

    String currentUserId = ...;
    event.setUserId(currentUserId);

    String userIpAddress = ...;
    event.setUserIpAddress(userIpAddress);

    event.setSource("myApplicationName");

    // add arbitrary user context information to the
    // userContext map
    event.getUserContext().put("some", "thing");
  }
}

步骤 3:注册 ReadAuditPrepare 实现

如果启用了类路径扫描,则可以自动检测 ReadAuditPrepare 的实现(就像找到实体 Bean 等一样)。也就是说,如果启用了扫描,则无需显式注册 ReadAuditPrepare 实现,而是会找到并实例化它。

如果未使用扫描或 ReadAuditPrepare 实现具有依赖项,并且其实例化应在 Ebean 外部执行,则可以使用 DatabaseConfig 显式注册它。

// example code explicitly registering the ReadAuditPrepare implementation

MyReadAuditPrepare readAuditPrepare = ...;

DatabaseConfig config = new DatabaseConfig();
...

// register explicitly here
config.setReadAuditPrepare(readAuditPrepare);


...
Database database = DatabaseFactory.create(config);

步骤 4:配置日志记录

ReadAuditLogger 的默认实现将查询计划条目记录到 io.ebean.ReadAuditQuery,并将读取事件记录到 io.ebean.ReadAudit。查询计划包含完整的 SQL,将这些内容单独记录意味着读取事件不必包含已执行的完整 SQL,而是可以使用 Bean 类型和查询键来引用/查找关联的 SQL。这减少了读取事件日志的体积/大小。

以下 logback xml 配置中有 2 个附加程序。READAUDIT_QUERY_LOG 用于记录查询计划,READAUDIT_LOG 用于记录读取 Bean 事件。

<!-- LOGBACK configuration: separate loggers for the read auditing -->

<appender name="READAUDIT_QUERY_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <File>log/readAuditQuery.log</File>
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <FileNamePattern>log/readAuditQuery.log.%d{yyyy-MM-dd}</FileNamePattern>
    <MaxHistory>90</MaxHistory>
  </rollingPolicy>
  <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
    <pattern>%d{HH:mm:ss.SSS} %msg%n</pattern>
  </encoder>
</appender>

<appender name="READAUDIT_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <File>log/readAudit.log</File>
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <FileNamePattern>log/readAudit.log.%d{yyyy-MM-dd}</FileNamePattern>
    <MaxHistory>90</MaxHistory>
  </rollingPolicy>
  <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
    <pattern>%d{HH:mm:ss.SSS} %msg%n</pattern>
  </encoder>
</appender>


<logger name="io.ebean.ReadAuditQuery" level="TRACE" additivity="false">
  <appender-ref ref="READAUDIT_QUERY_LOG"/>
</logger>

<logger name="io.ebean.ReadAudit" level="TRACE" additivity="false">
  <appender-ref ref="READAUDIT_LOG"/>
</logger>

可选:ReadAuditLogger 实现

如果默认日志不适合您,您可以实现 ReadAuditLogger 来控制如何记录事件。将日志记录到消息队列、直接记录到数据存储等。

Query.setDisableReadAuditing()

对于特定查询,您可以明确地将其从读取审核中排除。典型的用例是查询在应用程序内部用于填充缓存或处理海量数据,而您不希望将其写入读取审核日志。