1,什么是审计日志?
LightDB 审计扩展(ltaudit)通过标准的 LightDB 日志记录工具提供详细的会话和/或对象审计日志记录。
Ltaudit 的目标是为 LightDB 用户提供生成符合政府、财务或 ISO 认证要求的审计日志的能力。
审计是对个人或组织帐目的正式检查,通常由独立机构进行。由 ltaudit 收集的信息正确地称为审计跟踪或审计日志。本文档使用审计日志这一术语。
2,如何启动审计日志?
如图,在此示例中,会话审计日志记录用于记录 DDL 和 SELECT 语句。注意,由于未启用 WRITE 类,因此插入语句未被记录
SQL:
set ltaudit.log = 'read, ddl';
create table account
(
id int,
name text,
password text,
description text
);
insert into account (id, name, password, description)
values (1, 'user1', 'HASH1', 'blah, blah');
select *
from account;
Log Output 日志输出:
AUDIT: SESSION,1,1,DDL,CREATE TABLE,TABLE,public.account,create table account
(
id int,
name text,
password text,
description text
);,<not logged>
AUDIT: SESSION,2,1,READ,SELECT,,,select *
from account,,<not logged>
3,我们如何全文检索记录审计日志的内容以及全文检索日志内容?
3.1审计日志表如何建表?
create table if not exists lem_db_log_audit
(
id bigserial not null,
instance_ip varchar(128),
instance_port integer,
instance_name varchar(64),
log_file varchar(200),
log_file_pointer bigint,
db_log_message text,
db_log_level integer,
db_log_time timestamp(6) not null,
sample_time timestamp(6) default CURRENT_TIMESTAMP not null,
timeline integer not null,
application_name varchar(255),
user_name varchar(100),
database_name varchar(100),
db_log_sql text,
log_sql_tsv tsvector2 default ‘’::tsvector2 not null,
parameter text
) partition by range (sample_time);
–创建索引
drop index if exists lem_db_log_audit_rum;
CREATE INDEX if not exists lem_db_log_audit_rum ON lem_db_log_audit USING rum (log_sql_tsv rum_tsvector2_addon_ops, db_log_time) WITH (attach = ‘db_log_time’, to = ‘log_sql_tsv’);
drop index if exists lem_db_log_audit_time;
CREATE INDEX if not exists lem_db_log_audit_time ON lem_db_log_audit (id,db_log_time DESC);
3.1,java中如何建立把审计日志入库?
可以把要全文检索要查询的条件拼接到审计日志里面去,并用 " "分割,如图,便可利用instance_ip,instance_port,user_name,database_name进行全文检索。
private String addQueryCondition(LemDbLogAudit lemDbLogAudit) {
StringBuffer sql = new StringBuffer();
sql.append(lemDbLogAudit.getDbLogSql())
.append(" instance_ip=").append(lemDbLogAudit.getInstanceIp())
.append(" instance_port=").append(lemDbLogAudit.getInstancePort());
if (StringUtils.isNotBlank(lemDbLogAudit.getUserName())) {
sql.append(" user_name=").append(lemDbLogAudit.getUserName());
}
if (StringUtils.isNotBlank(lemDbLogAudit.getDatabaseName())) {
sql.append(" database_name=").append(lemDbLogAudit.getDatabaseName());
}
return sql.toString();
}
其次入库的日志要先分词然后再入库
/**
* 过滤 / 分词 适配pg 返回分词后 字符串
*
* @param line 日志原文
* @return
*/
public static String getSegmentStr(String line) {
List<SegToken> segTokens = getSegTokens(line);
segTokens.removeIf(seg -> seg.getWord().length() == 1);
LinkedHashMap<String, List<String>> tokens = new LinkedHashMap<>(120000);
int size = segTokens.size();
for (int f = 0; f < size; f++) {
tokens.putIfAbsent(segTokens.get(f).word, new ArrayList<>());
tokens.get(segTokens.get(f).word).add(String.valueOf(f + 1));
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, List<String>> entry : tokens.entrySet()) {
// 临时解决 tsvector 大小限制,升级 tsvector2 后可视情况撤销 wxj todo
if (sb.toString().getBytes(StandardCharsets.UTF_8).length >= TSV_MAX_SIZE - 128) {
break;
}
sb.append(replaceKeyword(entry.getKey())).append(":").append(StringUtils.join(entry.getValue(), ',')).append(" ");
}
return sb.toString();
}
3.2,java中xml如何全文检索审计日志?
如图要检索的条件用连接,并且按照时间顺序降序排序
<select id="getAuditLog" parameterType="com.hundsun.lightdb.model.database.LemDbLogAuditDTO" resultType="com.hundsun.lightdb.model.database.LemDbLogAuditVO">
select
*
from lem_db_log_audit
<where>
<trim prefix=" log_sql_tsv @@ (CONCAT(" suffix=")::tsquery)">
<trim suffixOverrides=",'&',">
<if test="instanceIp != null and instanceIp!= ''">
'instance_ip=',#{instanceIp},'&',
</if>
<if test="instancePort != null and instancePort >0">
'instance_port=',#{instancePort},'&',
</if>
<if test="userName != null and userName != ''">
'user_name=',#{userName},'&',
</if>
<if test="databaseName != null and databaseName != ''">
'database_name=',#{databaseName},'&',
</if>
<if test="dbLogSql != null and dbLogSql != ''">
#{dbLogSql},'&',
</if>
</trim>
</trim>
<if test="startTime != null and startTime != ''">
and db_log_time <![CDATA[ >= ]]> to_timestamp(#{startTime},'yyyy-MM-dd hh24:mi:ss')
</if>
<if test="endTime != null and endTime != ''">
and db_log_time <![CDATA[ <= ]]> to_timestamp(#{endTime},'yyyy-MM-dd hh24:mi:ss')
</if>
</where>
order by <![CDATA[ db_log_time <=| ]]> '${nowTime}'
</select>